扩展KMP算法(Extend KMP) 学习小记 Hdu 4333 Revolving Digits

前几天复习了KMP,现在来学习exKMP。

exKMP的作用是:求出一个串所有后缀串(即s[i...len])和模式串的最长公共前缀。

网上学习资料版本不多,看来看去还是 刘雅琼 的PPT 《扩展的KMP算法》 最好理解。

这里有一个字符串算法大集合:字符串:KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组 - 星星的日志


Hdu 4333 Revolving Digits

题意:给出一个不含前导0的数字,每一次把它的最后一位移动到最前面,一直持续下去,分别求形成的数字小于,等于和大于原来数的个数。

例如:134可以形成134,341,413三个数,所以分别是1,1,1。

如果移动过程中出现前导0,则去掉前导0,并认为形成了新的数字。

以下分析和代码参考了kuangbin大神的:http://www.cnblogs.com/kuangbin/archive/2012/11/09/2763242.html


扩展KMP能求出一个串所有后缀串(即s[i...len])和模式串的最长公共前缀。于是只要将这个串复制一遍,求出该串每个后缀与其本身的最长公共前缀即可,当公共前缀>=len时,显然相等,否则只要比较下一位就能确定这个串与原串的大小关系。

至于重复串的问题,只有当这个串有循环节的时候才会产生重复串,用KMP的next数组求出最小循环节,用长度除以最小循环节得到循环节个数,在将3个答案都除以循环节个数即可。

#include 
#include 

const int N=2000010;
#define max(a,b) ((a)>(b)?(a):(b))

int next[N];  // next[i]表示T[i..m]与T的最长公共前缀长度
int extend[N];// extend[i]表示S[i..n]与T的最长公共前缀长度

void exKMP (char s[],char t[]) //s为主串,t为模板串
{
	int i,j=0,p,L;
	int lens=strlen(s);
	int lent=strlen(t);
	next[0]=lent;
	
	while (j+1=0 && pattern[i]!=pattern[j])  
            j=next[j];  
        j++,i++;  
        if (pattern[j]==pattern[i])  
            next[i]=next[j];  
        else  
            next[i]=j;  
    }  
}

char source[N],after[N];

int main ()
{
	int T;
	scanf("%d",&T);
	for (int Cas=1;Cas<=T;Cas++)
	{
		scanf("%s",source);
		int len=strlen(source);
		strcpy(after,source);
		strcat(after,source);
		exKMP(after,source);
		int cnt1=0,cnt2=0,cnt3=0;

		for (int i=0;i=len) cnt2++;
			else
			{
				if (after[i+extend[i]]


你可能感兴趣的:(学习轨迹,KMP,exKMP,字符串)