字符串模板

kmp

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 1e6 + 9;
const ll inf = 0x3f3f3f3f;
char a[N];
char b[N];
int ne[N];
void solve() {
    scanf("%s", (a + 1));
    scanf("%s", (b + 1));
    int n = strlen(b + 1);
    int m = strlen(a + 1);
    for (int i = 2, j = 0; i <= n; i ++) {
        while (j && b[i] != b[j + 1])j = ne[j];
        ne[i] = (b[j + 1] == b[i]?++j:j);
    }
    for (int i = 1, j = 0; i <= m; i ++) {
        while ( j && b[j + 1] != a[i])j = ne[j];
        if (b[j + 1] == a[i])j++;
        if (j == n) {
            printf("%d\n", i-n + 1  );
        }
    }
    for (int i = 1; i <= n; i ++) printf("%d ", ne[i]);
}
signed main() {
   ll t = 1;//cin >> t;
   while (t--) solve();
}

ac自动机

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 1e5 + 9;
const ll inf = 0x3f3f3f3f;
int n;
vector<int>G[N];
string ch[N];
queue<int>q;
int dp[N];
struct AC {
    int tr[N][27],  idx;
    string str;
    int ne[N];

    void init() {
        memset(tr, 0, sizeof tr);
        memset(ne, 0, sizeof ne);
        memset(dp, 0, sizeof dp);
        memset(ch, 0, sizeof ch);
        for (int i = 0; i <= n; i ++) {
            G[i].clear();
        }
        idx = 0;
    }
    void insert() {
        int p = 0;
        for (int i = 0; str[i]; i ++) {
            int t = str[i] - 'a';
            if (!tr[p][t])tr[p][t] = ++ idx;
            p = tr[p][t];
        }
        ch[p] = str;
    }
    void build() {
        while (!q.empty())q.pop();
        for (int i = 0; i < 26; i ++) 
            if (tr[0][i])q.push(tr[0][i]);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (int i = 0; i < 26; i ++) {
                int p = tr[u][i];
                if (p) {//这里是手画理解的
                    ne[p] = tr[ne[u]][i];
                    q.push(p);
                } else 
                    tr[u][i] = tr[ne[u]][i];
            } 
        }
    }
}T;
vector<string> ans;
int ans_cnt;

void solve() {
while (~scanf("%d", &n)) {
    if (n == 0)exit(0);
    ans_cnt = 0;
    T.init();
    for (int i = 0; i < n; i ++) {
        cin >> T.str;
        T.insert();
    }
    T.build();
    for (int i = 1; i <= T.idx; i ++) {
        G[i].push_back(T.ne[i]);
        G[T.ne[i]].push_back(i);
    }
    cin >> T.str;
    int res = 0;
    for (int i = 0, j = 0; T.str[i]; i ++) {
        int t = T.str[i] - 'a';
        while (j && !T.tr[j][t])j = T.ne[j];
        if (T.tr[j][t]) j = T.tr[j][t];
        int p = j;
        while (p ) {//这里就正常找
            dp[p]++;
            p = T.ne[p];
        }
    }
    for (int i = 0; i <= T.idx; i ++) {
        if (ch[i].size() != 0) {
            if (dp[i] > ans_cnt) {
                ans_cnt = dp[i];ans.clear();
                ans.push_back(ch[i]);
            } else if (dp[i] == ans_cnt){
                ans.push_back(ch[i]);
            }
        }
    }
    cout << ans_cnt <<"\n";
    for (auto s:ans)cout << s << "\n";
}
}
signed main() {
   ll t = 1;//cin >> t;
    //scanf("%d", &t);
   while (t--) {
      solve();
   }
}

后缀数组

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 1e6 + 9;
const ll inf = 0x3f3f3f3f;
struct Suffix_Array{
    int n,m,x[N],y[N],H[N],SA[N],cnt[N],rank[N],Height[N];char s[N];
    //Suf[i]: s[i,n]
    //len: 已经求出了长度为len的串的排名
    //x[i]: Suf[i]的排名 (排序第一关键字) (上一次排序后得到的rank[i])
    //y[i]: 按第len个字符排出来的顺序(排序第二关键字) (第二关键字排名为i的数的位置)
    //H[i]: H[i]=Height[rank[i]] 即 LCP(Suf[i],Suf[SA[rank[i]-1]])
    //SA[i]: 排名为i的后缀第一个字符所在位置
    //cnt[i]: 第一关键字排名为 i(1~i)的数有多少个
    //rank[i]: Suf[i]的排名
    //Height[i]: Height[i]=H[SA[i]] 即 LCP(Suf[SA[i]],Suf[SA[i-1]])
    inline void get_SA(){
        m=128;
        memset(cnt, 0, sizeof cnt);
        memset(rank, 0, sizeof rank);
        for(int i=1;i<=n;++i)++cnt[x[i]=s[i]];
        for(int i=2;i<=m;++i)cnt[i]+=cnt[i-1];
        for(int i=n;i>=1;--i)SA[cnt[x[i]]--]=i;
        for(int len=1;len<=n;len<<=1){
            int t=0;
            for(int i=n-len+1;i<=n;++i)y[++t]=i;
            for(int i=1;i<=n;++i)if(SA[i]>len)y[++t]=SA[i]-len;
            for(int i=1;i<=m;++i)cnt[i]=0;
            for(int i=1;i<=n;++i)++cnt[x[i]];
            for(int i=2;i<=m;++i)cnt[i]+=cnt[i-1];
            for(int i=n;i>=1;--i)SA[cnt[x[y[i]]]--]=y[i],y[i]=0;
            swap(x,y);
            x[SA[1]]=m=1;//把旧的x存进了y并清零x
            for(int i=2;i<=n;++i)
                x[SA[i]]=(y[SA[i]]==y[SA[i-1]]&&y[SA[i]+len]==y[SA[i-1]+len])?m:++m;//注意这里的SA[i]+len和SA[i-1]+len有可能访问到n+1,所以上面的N最好稍开大一点,不要尝试卡这点小常数空间
            if(m==n)break;
        }
        
    }
    inline void get_Height(){
        for(int i=1;i<=n;++i)rank[SA[i]]=i;
        for(int i=1,k=0;i<=n;++i){
            if(rank[i]==1)continue;
            if(k)--k;//H[i-1]-1<=H[i]
            int j=SA[rank[i]-1];
            while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])++k;
            Height[rank[i]]=k;
        }
//        for(int i=1;i<=n;++i)printf("%d ",Height[i]);
    }
}SA;
void solve() {
    cin >> (SA.s + 1);
    SA.n = strlen(SA.s + 1);
    SA.get_SA();
    SA.get_Height();
    
}
signed main() {
   ll t = 1;//cin >> t;
   while (t--) {
      solve();
   }
}
posted @ 2021-08-20 10:59  u_yan  阅读(45)  评论(0编辑  收藏  举报