zoj 3643 Keep Deleting

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4811

首先肯定是KMP。然后刚开始想的是每删一次,做一次kmp,但是那样肯定会超时,所以就想一种可以利用了之前kmp信息的数据结构,看了一下别人的报告,知道了

是栈这一种数据结构。然后每一次取出栈的最顶端就可以了。

关于kmp,在说几句。我自己的设置的next数组的信息是当,当前位匹配失效是 ,他应该跳到哪一位去继续匹配。

这里的当前位匹配失效指的是 s1当前位的下一位和s2的第i位不等。

View Code
#include<iostream>

#include<stdio.h>

#include<string.h>

#include<algorithm>

#include<stack>

using namespace std;

const int maxn=512010;

char s1[maxn];

char s2[maxn];

int next[maxn];

int main()

{

    int ans;

    while(scanf("%s%s",s1,s2)!=EOF)

    {

        int len1=strlen(s1);

        int len2=strlen(s2);

        stack<int>s;

        memset(next,0,sizeof(next));

 next[0]=-1;//当第一位匹配失效是,跳到-1 ,即字符串的最左端外面

        for(int i=1;i<len1;i++)

        {

    int pre=next[i-1];//算第i位时,已经知道前面的,pre要指向i-1位

            while(pre!=-1&&s1[pre+1]!=s1[i])

                pre=next[pre];

            if(s1[pre+1]==s1[i])pre++;//一定是下一位相等,然后加1

            next[i]=pre;

        }

        ans=0;

        for(int j=-1, i=0;i<len2;i++)

        {

            while(j>=0&&s1[j+1]!=s2[i])

                j=next[j];//大于等于0就可以回退

            if(s2[i]==s1[j+1])j++;//下一位相等

            s.push(j);

            if(j==len1-1)

            {

                ans++;

                for(int t=0;t<len1;t++)

                    s.pop();

                if(!s.empty())

                    j=s.top();

                else

                    j=-1;

            }

        }

        cout<<ans<<endl;

    }

    return 0;

}

你可能感兴趣的:(ZOJ)