hdu 4749 (转化的KMP)

//hdu 4749

/*

题意:给出两个数列(可以看成串),问最多能在串1中找出几个不重叠的substring,使得这些substring的元素的相对大小关系与串

2相同(显然,长度也要与串2相同)。

解题思路:kmp。。比赛的时候有想到这个思路,但一直不知道怎么搞定这个相对大小关系。其实很简单。。

count(AiAn+1)=count(Bi>Bn+1),i=1..n

这样不就行了吗?那怎么弄这个count呢?暴力记录就好了,开两个二维数组g1[i][j]表示串1中,到j为止,有多少个i。g2[i][j]表

示串2中,到j为止,有多少个i。其中i的范围1-25完全可以接受。然后就是kmp的匹配过程了,这个匹配并不是绝对的匹配,而是说,

我们的相对大小关系相同。比如,我们要看串1的x位置,能否和串2的y位置匹配,那我们就看串1里面,[x-y+1,x-1]这段区间内(注

意这个区间的长度是y-1,我们要匹配的是x,y,所以前y-1个长度肯定是匹配好的),小于a[x]的数的个数,以及等于a[x]的数的个

数,是否相应的与串2里面,[1,y-1]这段区间内,小于b[y]的数的个数,等于b[y]的数的个数相等。这个就用刚才记录的数组暴力算好

了(当然也可以用树状数组,但是字符集只有25,完全可以暴力),其他就跟普通的kmp一样了。在匹配的过程中,记录下匹配点,然

后去枚举,一旦找到匹配点,就ans+1,然后往后跳m长度去找匹配点,这样贪心。

*/

#include
#include
#include
#include
using namespace std;
#define MAX 100500
int next[MAX],s[MAX],t[MAX];//s是主串,t是待判断的子串
int nums[MAX][30],numt[MAX][30];
int n,m,k;
void init()
{
    int i,j;
    memset(nums,0,sizeof(nums));
    memset(numt,0,sizeof(numt));
    nums[1][s[1]]=numt[1][t[1]]=1;
    for(i=2;i<=n;i++)
    {
        memcpy(nums[i],nums[i-1],sizeof(nums[0]));
        nums[i][s[i]]++;
    }
    for(i=2;i<=m;i++)
    {
        memcpy(numt[i],numt[i-1],sizeof(numt[0]));
        numt[i][t[i]]++;
    }
}
void CalcNext(int length)  //t串的最后一个字符的下标
{
    memset(next,0,sizeof(next));
	int i,j,si,ei,sj,ej,tt;
	next[1]=0;
	j=0;
	for(i=1;i<=length;)
    {
        si=ei=sj=ej=0;
	    for( tt=1;tt0&&t[j+1]!=t[i]) j=next[j];
        if(j==0||(si==sj&&ei==ej)) {i++;j++;next[i]=j;}
        else j=next[j];
    }
}
void KMP()  //s串的长度,t串的长度
{
	int i,j,si,ei,sj,ej,pre=-1,ans=0;
	j=1;
	for(i=1;i<=n;)
    {
        si=ei=sj=ej=0;
        for(int tt=1;tt0&&t[j+1]!=s[i]) j=next[j];
        if(j==0||(si==sj&&ei==ej)) {i++;j++;}
        else j=next[j];
        if(j==m+1)
        {
            if(i-1-m>=pre){
                ans++;
                pre=i-1;
            }
            j=next[j];
        }
    }
    printf("%d\n",ans);
}
int main()
{
    int i,j;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        for(i=1;i<=n;i++) scanf("%d",&s[i]);
        for(i=1;i<=m;i++) scanf("%d",&t[i]);
        init();
        CalcNext(m);
        KMP();
    }
    return 0;
}

你可能感兴趣的:(字符串)