您的位置:首页 > 其它

KMP算法做题感悟。

2018-01-22 20:51 295 查看
在字符串匹配题运用kmp算法。
其核心还是next数组的建立,get_next函数的理解和实现。
void get_next()
{
int i=0,j=-1;
ne[0]=-1;
while(i<n){
if(j==-1||a[i]==a[j])
ne[++i]=++j;
else
j=ne[j];
}
}

从next数组和a串的对比中会发现许多规律,其中是对next的深入理解。
第一题(剪花布条)
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?
Input输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。
Output输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。
Sample Input
abcde a3
aaaaaa  aa
#

Sample Output
0
3


注意:每匹配一次,文本串要剪去相应的模串;

第二题(HDU 3336 Count the string )

It is well known that AekdyCoin is good at string problems as well as number theory problems. When given a string s, we can write down all the non-empty prefixes of this string. For example:

s: "abab"

The prefixes are: "a", "ab", "aba", "abab"

For each prefix, we can count the times it matches in s. So we can see that prefix "a" matches twice, "ab" matches twice too, "aba" matches once, and "abab" matches once. Now you are asked to calculate the sum of the match times for all the prefixes. For "abab",
it is 2 + 2 + 1 + 1 = 6.

The answer may be very large, so output the answer mod 10007.
InputThe first line is a single integer T, indicating the number of test cases.

For each case, the first line is an integer n (1 <= n <= 200000), which is the length of string s. A line follows giving the string s. The characters in the strings are all lower-case letters.
OutputFor each case, output only one number: the sum of the match times for all the prefixes of s mod 10007.Sample Input
1
4
abab

Sample Output
6


这一题是求文本串的前缀在文本串中出现的次数之和;
刚开始用循环递增复制出前缀在和文本串一一比对,既麻烦还会超时。
慢慢的从写next数组和文本串的对比中发现了规律;
位置   0  1  2 3 4
 串      a  b a b
next   -1 0 0 1 2

设dp【i】:以string[i]结尾的子串总共含前缀的数量

所以dp[j]=dp[i]+1,即以i结尾的子串中含前缀的数量加上前j个字符这一前缀

ans = T%M;
for(int i = 1; i <= T; i++)
{
int temp = ne[i];
while(temp)
{
4000
ans = (ans + 1) % M;
temp = ne[temp];

}
}


第三题
hdu1358

For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the prefix is a periodic string. That is, for each i (2 <= i <= N) we want to know the largest K > 1 (if there
is one) such that the prefix of S with length i can be written as A K , that is A concatenated K times, for some string A. Of course, we also want to know the period K.

InputThe input file consists of several test cases. Each test case consists of two lines. The first one contains N (2 <= N <= 1 000 000) – the size of the string S. The second line contains the string S. The input file ends with a line, having the number zero
on it.
OutputFor each test case, output “Test case #” and the consecutive test case number on a single line; then, for each prefix with length i that has a period K > 1, output the prefix size i and the period K separated by a single space; the prefix sizes must be
in increasing order. Print a blank line after each test case.
Sample Input
3
aaa
12
aabaabaabaab
0

Sample Output
Test case #1
2 2
3 3

Test case #2
2 2
6 2
9 3
12 4


我在做第二题时是基于第五题的方法;这里是求整个字符串的前缀是否存在循环节;以及循环次数;
所以加一个for循环一次提出它的前缀
m=strlen(a);
for(int i=1;i<m;i++){
k=i+1;
if(k%(k-ne[k])==0&&k!=k-ne[k]){
printf("%d %d\n",k,k/(k-ne[k]));



poj 2406

Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 =
"" (the empty string) and a^(n+1) = a*(a^n).
Input
Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

Output
For each s you should print the largest n such that s = a^n for some string a.

Sample Input
abcd
aaaa
ababab
.

Sample Output
1
4
3

Hint
This problem has huge input, use scanf instead of cin to avoid time limit exceed.

核心还是next数组得建立;

下面的规律是从next数组中发现的;(我用ne[]表示next数组);

如果字符串存在循环节,那么串的最后元素对应循环节的最后一个元素,所以n-ne
表示循环节的长度,所以,

当且仅当n(这里的n是数组得长度)整除(n-ne
)时存在那个循环节,否则就是本身1;
if(n%(n-ne
)==0)
printf("%d\n",n/(n-ne
));//这里n-ne
是循环节的长度
else
printf("1\n");


第六题
POJ2752 Seek the Name, Seek the Fame

The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the
innovative little cat works out an easy but fantastic algorithm:

Step1. Connect the father's name and the mother's name, to a new string S.

Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S).

Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings
of S? (He might thank you by giving your baby a name:)

Input
The input contains a number of test cases. Each test case occupies a single line that contains the string S described above.

Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000.

Output
For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby's name.

Sample Input
ababcababababcabab
aaaaa

Sample Output
2 4 9 18
1 2 3 4 5


此题是看前多少位的前缀和后缀相等,若相等,输出长度;

如果前缀和后缀相同,那后缀必然包括最后一位;而next[]数组储存的就是这个位置与前面相同的位置之间的关系;
于字符串s的第i个字符s[i],next[i]定义为字符s[i]前面最多有多少个连续的字符和字符串s从初始位置开始的字符匹配。
int j=0;
int temp=n;
while(temp!=0)
{
b[j]=temp;
j++;
temp=ne[temp];
}
for(int i=j-1;i>=0;i--){

printf("%d ",b[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: