zoukankan      html  css  js  c++  java
  • [NOI2014] 动物园

    Description

    (num[i]) 表示字符串 (S) 的前 (i) 个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,这种字符串的数量。给定一个字符串,求出它的 (num[])

    Solution

    (ans[i]) 表示字符串 (S) 的前 (i) 个字符构成的子串,既是它的后缀同时又是它的前缀,这种字符串的数量,显然 (ans[]) 可以在标准 KMP 的过程中很容易地处理出

    那么要得到每一个 (num[i]) 我们只需要以 (i) 为起点,用 (next()) 不断迭代,直到 (i'le frac i 2),此时的 (ans[i']) 就是所求

    每次都暴力迭代,复杂度显然无法接受,一种方案是对 (next())(2^j) 次迭代结果倍增处理,较为麻烦

    考虑在一个类似 KMP 的过程中动态维护 (j),但不同的是,每次处理完后,将 (j)(next()) 不断迭代,直到 (jle frac i 2),此时的 (ans[j]) 就是所求

    #include <bits/stdc++.h>
    using namespace std;
    
    const int mod = 1e9+7;
    
    char p[1000005];
    int n,m,fail[1000005],ans[1000005],num[1000005];
    
    void solve() {
        memset(p,0,sizeof p);
        memset(fail,0,sizeof fail);
        memset(ans,0,sizeof ans);
        memset(num,0,sizeof num);
    	cin>>p+1;m=strlen(p+1);
    	for(int i=2;i<=m;i++) {
    		int j=fail[i-1];
    		while(p[j+1]-p[i] && j) j=fail[j];
    		if(p[j+1]==p[i]) ++j;
    		fail[i]=j;
    		if(j>0) ans[i]=ans[j]+1;
    	}
    	for(int i=1;i<=m;i++) ans[i]++;
    	int j=0;
        for(int i=2;i<=m;i++) {
            while(p[j+1]-p[i] && j) j=fail[j];
            if(p[j+1]==p[i]) ++j;
            while(j*2>i && j) j=fail[j];
            num[i]=ans[j];
        }
        long long res=1;
        for(int i=2;i<=m;i++) res*=num[i]+1, res%=mod;
        cout<<res<<endl;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        int n;
        cin>>n;
        while(n--) solve();
    }
    
    
  • 相关阅读:
    Trapping Rain Water
    Construct Binary Tree from Preorder and Inorder Traversal
    Flatten Binary Tree to Linked List
    Permutations II
    Unique Paths II
    Path Sum II
    Unique Binary Search Trees II
    evdev module-----uinput.py
    evdev module-----events.py
    evdev module-----device.py
  • 原文地址:https://www.cnblogs.com/mollnn/p/13192220.html
Copyright © 2011-2022 走看看