SCU-4438-Censor(kmp/哈希+模擬棧)

題目鏈接:http://acm.scu.edu.cn/soj/problem.action?id=4438
給出s1、s2,要你刪除s2中出現的第一個s1,並將剩下的合併成一個新的串,再繼續找,直到找不到s1,輸出最後的串。
///主要想記錄一下模擬棧的使用(比賽的時候都沒有想到它T_T,後面想用kmp裏面的next數組優化下我的假算法,又不會寫T_T)

kmp+模擬棧

KMP算法中,我們在主串中找模擬串,找到後就從起始點的下一位又開始匹配,找下一個模擬串出現的位置。但這裏去掉s1後,它的前後有可能合併成一個新的s1串。這裏我們可以用一個模擬棧,從前往後處理,在模擬棧中去匹配s1,我們用cou表模擬棧的長度,當出現s1,就執行操作:cou-=strlen(s1),直接O(1)“刪掉”出現的s1,然後再往模擬棧中放入後面的字符。需要注意的是cou-=strlen(s1)後,j應該回溯到哪裏(需要用一個數組來記錄模擬棧每個位置前可以匹配到 s1前綴的長度)

代碼:

//pos[cou]表示,模擬棧中,cou爲前可以匹配到多少個字符
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
//#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define mid ((l + r)>>1)
#define chl root<<1
#define chr root<<1|1
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int manx=5e6+10;
char p[manx],str[manx],s[manx];
int net[manx],pos[manx];
int ls,lp;
void getnext()
{
    net[0]=-1;
    int k=-1,j=0;
    while(j<lp)
    {
        if(k==-1||p[k]==p[j])
            net[++j]=++k;
        else
            k=net[k];
    }
}
int ans_len()
{
    int cou=0,i=0,j=0;
    pos[0]=0;
    while(i<ls)
    {
        str[cou]=s[i++];
        while(j!=-1&&p[j]!=str[cou])
            j=net[j];
        cou++,j++;
        pos[cou]=j;
        if(j==lp)//if這部分就是kmp中改動的部分
        {
            cou-=lp;
            j=pos[cou];
        }
    }
    return cou;
}
int main()
{
    while(scanf("%s%s",p,s)!=EOF)
    {
        lp=strlen(p);
        ls=strlen(s);
        getnext();
        str[ans_len()]='\0';
        printf("%s\n",str);
    }
    return 0;
}
字符串哈希+模擬棧

每次判斷模擬棧中倒數Len個字符的哈希值和s1是否相等
///真的每次寫哈希都會錯,不是哪裏沒有取模,就是哪裏寫錯了wawadaku

代碼:

//hhash[cou]表示前min(cou+1,len)個字符串的哈希值
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
//#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define mid ((l + r)>>1)
#define chl root<<1
#define chr root<<1|1
using namespace std;
//typedef unsigned long long LL;
typedef long long LL;
const LL manx=5e6+10;
const LL mmm=1e7+19;
const LL mod=1e9+7;
char p[manx],s[manx],ans[manx];
LL lp,ls,ttrue,mul[manx],hhash[manx];
int main()
{
    mul[0]=1;
    for(int i=1;i<=5e6;i++)
        mul[i]=(mul[i-1]*mmm)%mod;
    while(scanf("%s%s",p,s)!=EOF)
    {
        ttrue=0;
        lp=strlen(p);
        ls=strlen(s);
        for(int i=0;i<lp;i++)
            ttrue=(ttrue*mmm+p[i])%mod;
        int cou=0,i=0;
        while(i<ls)
        {
            ans[cou]=s[i++];
            if(cou==0)
                hhash[cou]=ans[0];
            else if(cou>=lp)
                hhash[cou]=((hhash[cou-1]-ans[cou-lp]*mul[lp-1]%mod+mod)*mmm%mod+ans[cou])%mod;
            else
                hhash[cou]=(hhash[cou-1]*mmm+ans[cou])%mod;
            if(hhash[cou]==ttrue)
                cou-=lp;
            cou++;
        }
        ans[cou]='\0';
        printf("%s\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章