传送门:POJ-3461
最简单的KMP题,找出第一个字符串在第二个字符串中出现次数。
#include
#include
#include
#define Memset(x, a) memset(x, a, sizeof(x))
using namespace std;
const int N=1e6+10;
char w[N],t[N];
int next[N];
int sum;
void getNext(const char P[],int next[]){
int m=strlen(P);
int i=0,j;
j=next[0]=-1;
while(i=m){
sum++;
j=next[j];//这儿修改很重要,不然会超时
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
sum=0;
Memset(next,0);
scanf("%s%s",w,t);
kmp(t,w,next);
printf("%d\n",sum);
}
return 0;
}
传送门:POJ-2752
思路:其实是next数组的使用
下面给出描述: (i>1)[下标从0开始]
next[i]的意义就是:前面长度为i的字串的【前缀和后缀的最大匹配长度】
那么这题怎么利用这个性质呢?
详细分析一下:【就用上面的第一个例子说明吧】
求出next值:[非修正] |
下标: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
串: a b a b c a b a b a b a b c a b a b |
next值: -1 0 0 1 2 0 1 2 3 4 3 4 3 4 5 6 7 8 9 |
#include
#include
#include
#define Memset(x, a) memset(x, a, sizeof(x))
using namespace std;
const int N=4e5+10;
int next[N],ans[N];
char s[N];
void getNext(const char P[],int next[]){
int m=strlen(P);
int i=0,j;
j=next[0]=-1;
while(i0){
ans[++cnt]=j;
j=next[j];
}
for(int i=cnt; i>0; i--)printf("%d ",ans[i]);
printf("%d\n",len);
}
return 0;
}
传送门:POJ-2406 Power Strings
思路:KMP,next表示模式串如果第i位(设str[0]为第0位)与文本串第j位不匹配则要回到第next[i]位继续与文本串第j位匹配。则模式串第1位到next[n]与模式串第n-next[n]位到n位是匹配的。所以思路和上面一样,如果n%(n-next[n])==0,则存在重复连续子串,长度为n-next[n]。
例如:a b a b a b
next:-1 0 0 1 2 3 4
next[n]==4,代表着,前缀abab与后缀abab相等的最长长度,这说明,ab这两个字母为一个循环节,长度=n-next[n];
#include
#include
#include
#define Memset(x, a) memset(x, a, sizeof(x))
using namespace std;
const int N=1e6+10;
int next[N];
char s[N];
void getNext(const char P[],int next[]){
int m=strlen(P);
int i=0,j;
j=next[0]=-1;
while(i
传送门:POJ-1961 Period
题意:
给你一个字符串,求这个字符串到第i个字符为止的循环节的次数。
比如aabaabaabaab,长度为12.到第二个a时,a出现2次,输出2.到第二个b时,aab出现了2次,输出2.到第三个b时,aab出现3次,输出3.到第四个b时,aab出现4次,输出4.
思路:
这道题就是上题的加强版而已。上一道题输出一个字符串的循环节出现的次数,这个是到第i个字符为止,其实就是多了一层循环。把这个字符串遍历一次即可,具体思路也以参考小白书的例题。
#include
#include
#include
#define Memset(x, a) memset(x, a, sizeof(x))
using namespace std;
const int N=1e6+10;
char s[N];
int next[N];
int n;
void getNext(const char P[],int next[]){
int m=strlen(P);
int i=0,j;
j=next[0]=-1;
while(i0&&i%(i-next[i])==0)printf("%d %d\n",i,i/(i-next[i]));
}
printf("\n");
}
return 0;
}