现在的位置: 首页 > 综合 > 正文

zoj 3643 Keep Deleting

2012年05月04日 ⁄ 综合 ⁄ 共 988字 ⁄ 字号 评论关闭

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;
}

抱歉!评论已关闭.