HDU - 6629 string matching (Extended KMP)

Topic links: Click here

Subject to the effect: Given a string s and a violent program for the longest common prefix and suffix for each original string solving s now asked a total of how many comparisons you need to do

Topic analysis: First, certainly not violence to simulate the time complexity of n * n, nor can the suffix array, this problem seems specially card time suffix array multiplication method nlogn get caught out, DC3 will be too large because the constant cards off the internet, said AC chance to be automatically memory card, because the entire ASCII character set is the scope of the code, it can only be solved by the expansion of KMP, extend the KMP solved extend [i] array in O (n) time, s longest string that represents common prefix and suffix for each matching string t, and such an action would correspond on this subject, and the position of the string to replace the string s t is the answer, remember special about each sentence match to the end of the second match, if not the end of a need to increase because the last match of that failure can be considered a match operation

Code:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
 
typedef long long LL;
 
const int inf=0x3f3f3f3f;
 
const int N=1e6+100;

char s[N];

LL Next[N],extend[N];
 
//预处理计算Next数组
void getNext(char str[])
{
    int i=0,j,po,len=strlen(str);
    Next[0]=len; //初始化Next[0]
    while(str[i]==str[i+1] && i+1<len) i++; Next[1]=i; //计算Next[1]
    po=1; //初始化po的位置
    for(i=2;i<len;i++)
    {
        if(Next[i-po]+i < Next[po]+po) //第一种情况,可以直接得到Next[i]的值
            Next[i]=Next[i-po];
        else //第二种情况,要继续匹配才能得到Next[i]的值
        {
            j = Next[po]+po-i;
            if(j<0) j=0; //如果i>po+Next[po],则要从头开始匹配
            while(i+j<len && str[j]==str[j+i]) j++; Next[i]=j;
            po=i; //更新po的位置
        }
    }
}
 
//计算extend数组
void EXKMP(char s1[],char s2[])
{
    int i=0,j,po,len=strlen(s1),l2=strlen(s2);
    getNext(s2); //计算子串的Next数组
    while(s1[i]==s2[i] && i<l2 && i<len) i++; extend[0]=i;
    po=0; //初始化po的位置
    for(i=1;i<len;i++)
    {
        if(Next[i-po]+i < extend[po]+po) //第一种情况,直接可以得到extend[i]的值
            extend[i]=Next[i-po];
        else //第二种情况,要继续匹配才能得到extend[i]的值
        {
            j = extend[po]+po-i;
            if(j<0) j=0; //如果i>extend[po]+po则要从头开始匹配
            while(i+j<len && j<l2 && s1[j+i]==s2[j]) j++; extend[i]=j;
            po=i; //更新po的位置
        }
    }
}
 
int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	int w;
	cin>>w;
	while(w--)
	{
		scanf("%s",s);
		int n=strlen(s);
		getNext(s);
		EXKMP(s,s);
		LL ans=0;
		for(int i=1;i<n;i++)
			ans+=extend[i]+(extend[i]!=n-i);
		printf("%lld\n",ans);
	}
	
 
 
 
 
 
	
	
	
	
	
	
	
	
	
	return 0;
}

 

Published 578 original articles · won praise 18 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_45458915/article/details/104116950