• BZOJ3670


    题目

    求出一个num数组一一对于字符串S的前i个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]。
    输出(prod_{i=1}^L(num[i]+1))对1,000,000,007取模的结果即可。

    题解

    先求出next数组。然后预处理一个tmp数组,它是num数组的后缀与前缀可以重叠的版本。
    和next数组求法类似,假设位置i前的tmp数组都求出来了,那么

    • tmp[0]=-1
    • 当j-1或s[i]s[j]时,tmp[i]=tmp[j]+1
    • 否则j=next[j],继续判断

    而求num数据就是加个2*(j + 1)<=(i + 1)的限制条件,其它步骤和求tmp数组一模一样。

    #include <bits/stdc++.h>
    
    #define endl '
    '
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define FILE freopen(".//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
    #define FI freopen(".//data_generator//in.txt","r",stdin)
    #define FO freopen("res.txt","w",stdout)
    #define pb push_back
    #define mp make_pair
    #define seteps(N) fixed << setprecision(N) 
    typedef long long ll;
    
    using namespace std;
    /*-----------------------------------------------------------------*/
    
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    #define INF 0x3f3f3f3f
    
    const int N = 1e6 + 10;
    const int M = 1e9 + 7;
    const double eps = 1e-5;
    char s[N];
    int nt[N];
    int num[N];
    int tmp[N];
    void getnext(char t[]) {
        int i = 0, j = -1;
        nt[i] = num[i] = tmp[i] = j;
        while(t[i]) {
            if(j == -1 || t[i] == t[j]) {
                i++;
                j++;
                nt[i] = j;
                tmp[i] = tmp[j] + 1;
                
            } else {
                j = nt[j];
            }
        }
        i = 0, j = -1;
        while(t[i]) {
            if(j == -1 || (t[i] == t[j] && 2 * (j + 1) <= (i + 1))) {
                i++;
                j++;
                num[i] = tmp[j] + 1;
            } else {
                j = nt[j];
            }
        }
    }
    
    
    int main() {
        IOS;
        int t;
        cin >>t;
        while(t--) {
            memset(num, 0, sizeof num);
            cin >> s;
            int len = strlen(s);
            getnext(s);
            int ans = 1;
            for(int i = 1; i <= len; i++) {
                ans = 1ll * ans * (num[i] + 1) % M;
                //cout << num[i] << " ";
            }
            //cout << endl;
            cout << ans << endl;
        }
    }
    
  • 相关阅读:
    CMD与bat操作
    XmlHelper XML通用类
    Regex正则表达式扩展
    LONG数据类型转换为VARCHAR2并相互转换
    CLOB数据类型截取SUBSTR_按开始位置偏移量
    12c rac On redhat 7
    DML_DDL_触发器
    Linux平台 Oracle 18c RAC安装
    hadoop 透明加密
    Poco::Crypto--加解密_RSA
  • 原文地址:https://www.cnblogs.com/limil/p/13502404.html
Copyright © 2020-2023  润新知