22.1 Knuth-Morris-Pratt算法
22.1.1 实例
PKU JudgeOnline, 3461, Oulipo.
22.1.2 问题描述
求字符串在另外一个字符串中出现了几次。
22.1.3 输入
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN
22.1.4 输出
1
3
0
22.1.5 分析
标准的KMP算法解决的问题。将KMP的伪代码一翻译就出来了。
22.1.6 程序
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int count;
char W[100002];
char T[1000002];
int prefix[1000002];
void computePrefix(char* P, int* prefix)
{
int m;
int k;
int q;
m = strlen(P) - 1;
prefix[1] = 0;
k = 0;
for(q = 2;q <= m; q++){
while(k> 0 && P[k + 1] != P[q]){
k = prefix[k];
}
if(P[k+ 1] == P[q])
{
k = k + 1;
}
prefix[q] = k;
}
}
void KMP_matcher(char* T, char* P){
int n;
int m;
int q;
int i;
n = strlen(T) - 1;
m = strlen(P) - 1;
computePrefix(P, prefix);
q = 0;
for(i = 1;i <= n; i++){
while(q> 0 && P[q + 1] != T[i]){
q = prefix[q];
}
if(P[q+ 1] == T[i])
{
q = q + 1;
}
if(q ==m)
{
count ++;
q = prefix[q];
}
}
}
int main()
{
int time;
cin >> time;
for(; time> 0; time--){
count = 0;
scanf("%s",&W[1]);
W[0] = '@';
scanf("%s",&T[1]);
T[0] = '@';
KMP_matcher(T, W);
cout << count << endl;
}
return 1;
}
22.2 Knuth-Morris-Pratt算法的前缀函数的应用
22.2.1 实例
PKU JudgeOnline, 2752, Seek the Name, Seek the Fame.
22.2.2 问题描述
输出一个字符串中所有前缀、后缀相等的长度。
22.2.3 输入
ababcababababcabab
aaaaa
22.2.4 输出
24 9 18
12 3 4 5
22.2.5 分析
该题的题意是这样的,给若干个字符串,判断该字符串前n个字符和后n个字符是否相同,按从小到大的顺序输出n,比如,给ababab,结果输出2 4 6,再比如ababcababababcabab 输出 2 4 9 18。
我们要根据kmp算法中的next函数来解决这个问题,以ababab为例加以说明:
String:ababab
Next: 0112345
这里根据后面的需要多计算了一位next值。
我们用ababab即作为主串有作为模式串来进行匹配,假设匹配到第7位时不匹配了(下标中1开始),要根据next[7](=5)的值继续匹配:
ababab*
ababab&
ababab*
ababab
可以由5得出4(5-1)是符合要求的,然后求next[5]=3,即继续这样匹配:
ababab*
ababab
可以由5得出2(3-1)是符合要求的,然后求next[3]=1,停止循环。
这样,我们依此输出2 4 6即可。
22.2.6 程序
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void computePrefix(char* P, int* prefix)
{
int m;
int k;
int q;
m = strlen(P) - 1;
// cout <<"m:" << m <<endl;
prefix[1] = 0;
k = 0;
// cout <<prefix[1] << " ";
for(q = 2;q <= m; q++){
while(k> 0 && P[k + 1] != P[q]){
k = prefix[k];
}
if(P[k+ 1] == P[q])
{
k = k + 1;
}
prefix[q] = k;
// cout << prefix[q] << "";
}
//cout << endl;
}
char S[400002];
int prefix[400002];
int result[400002];
int main()
{
int j,index, length;
while(scanf("%s", &S[1]) != EOF){
S[0] = '@';
computePrefix(S, prefix);
length = strlen(S) - 1;
j = length;
index = 0;
while(1)
{
j = prefix[j];
if(j== 0)
break;
result[++index] = j;
}
for(;index > 0; index-- ){
printf("%d", result[index]);
}
cout << length << endl;
}
return 1;
}
22.3 实例
PKU JudgeOnline, 2752, Seek the Name, Seek the Fame.
PKU JudgeOnline, 1961, Period.
PKU JudgeOnline, 2406, Power Strings.
PKU JudgeOnline, 3461, Oulipo.
本文章欢迎转载,请保留原始博客链接http://blog.csdn.net/fsdev/article