Hihocoder1015 KMP
题目链接:http://hihocoder.com/problemset/problem/1015
题意&思路:KMP版
基本上是靠自己试出来的。首先每个位置的fail值代表匹配值,即包括这个字符在内,得到前缀和后缀相同的最大前缀长度。如[0,j],[i-j,j]中设j为3,i为5,则fail[5] = j+1。
用文字叙述KMP流程
产生fail:
设第一个点fail[0] = 0,设j = fail[0];
i从1开始遍历,直到n-1:
循环:若j>0 并且 t[j] != t[i],j = fail[j-1]////注意这里
若t[j] == t[i] j++;
Fail[i] = j;
Match匹配(求所有匹配点):
遇到相同的,向后找;
遇到不相同,j的值变为fail[j-1]直到j为0;
j为n即模式串遍历完毕,记录,j变为fail[j-1];
源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
int const MAXT2 = 1000000+5;
int const MAXT1 = 10000+5;
void failure(char *t1,int *fail)
{
fail[0] = 0;
int j = fail[0];
for(int i=1; i<strlen(t1); i++){
while(j && t1[i]!=t1[j])
j = fail[j-1];
if(t1[i] == t1[j]) j++;
fail[i] = j;
}
}
int match(char *t1,char *t2,int *fail)
{
int res = 0,now = 0,j=0;
int n = strlen(t1);
int m = strlen(t2);
while(now + n - j <= m){
if(j == n){
res ++;
j = fail[j-1];
}
while(j && t1[j]!=t2[now]) j = fail[j-1];
if(t1[j] == t2[now]){
j++; now++;
}
else{
now++;
}
}
return res;
}
int main()
{
char t1[MAXT1],t2[MAXT2];
int fail[MAXT1];
int n;
scanf("%d",&n);
while(n--){
scanf("%s%s",t1,t2);
failure(t1,fail);
int ans = match(t1,t2,fail);
printf("%d\n",ans);
}
return 0;
}