• poj 2406 Power Strings 后缀数组解法


    连续重复子串问题

    poj 2406 Power Strings

    http://poj.org/problem?id=2406

    问一个串能否写成a^n次方这种形式。

    虽然这题用kmp做比较合适,但是我们还是用后缀数组做一做,巩固后缀数组的能力。

    对于一个串,如果能写出a^n这种形式,我们可以暴力枚举循环节长度L,那么后缀suffix(1)和suffix(1 + L)的LCP应该就是 lenstr - L。如果能满足,那就是,不能,就不是。

    这题的话da算法还是超时,等我学了DC3再写上来。

    其实这题可以不用枚举,考虑到如果能写成a^n这种形式,那么其循环节长度必定为 lenstr - height[rank[1]]

    给个图可能会更清楚

    如果是循环节,那么height[rank[1]]就是第1位的排名前后的lcp,肯定是第二个循环节那里的。

    然后暴力判断一下就行~dc3, 2750ms才能卡过去

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 3 * 1000000 + 20;
    const int N = maxn;
    #define F(x) ((x)/3+((x)%3==1?0:tb))
    #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
    int r[maxn];
    int wa[maxn],wb[maxn],wv[maxn],WS[maxn];
    int sa[maxn];
    int c0(int *r,int a,int b) {
        return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
    }
    int c12(int k,int *r,int a,int b) {
        if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
        else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];
    }
    void sort(int *r,int *a,int *b,int n,int m) {
        int i;
        for(i=0; i<n; i++) wv[i]=r[a[i]];
        for(i=0; i<m; i++) WS[i]=0;
        for(i=0; i<n; i++) WS[wv[i]]++;
        for(i=1; i<m; i++) WS[i]+=WS[i-1];
        for(i=n-1; i>=0; i--) b[--WS[wv[i]]]=a[i];
        return;
    }
    void dc3(int *r,int *sa,int n,int m) { //涵义与DA 相同
        int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
        r[n]=r[n+1]=0;
        for(i=0; i<n; i++) if(i%3!=0) wa[tbc++]=i;
        sort(r+2,wa,wb,tbc,m);
        sort(r+1,wb,wa,tbc,m);
        sort(r,wa,wb,tbc,m);
        for(p=1,rn[F(wb[0])]=0,i=1; i<tbc; i++)
            rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
        if(p<tbc) dc3(rn,san,tbc,p);
        else for(i=0; i<tbc; i++) san[rn[i]]=i;
        for(i=0; i<tbc; i++) if(san[i]<tb) wb[ta++]=san[i]*3;
        if(n%3==1) wb[ta++]=n-1;
        sort(r,wb,wa,ta,m);
        for(i=0; i<tbc; i++) wv[wb[i]=G(san[i])]=i;
        for(i=0,j=0,p=0; i<ta && j<tbc; p++)
            sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
        for(; i<ta; p++) sa[p]=wa[i++];
        for(; j<tbc; p++) sa[p]=wb[j++];
        return;
    }
    int rank[maxn], height[maxn];
    void calheight(int *r,int *sa,int n) { // 此处N为实际长度
        int i,j,k=0;        // height[]的合法范围为 1-N, 其中0是结尾加入的字符
        for(i=1; i<=n; i++) rank[sa[i]]=i; // 根据SA求RANK
        for(i=0; i<n; height[rank[i++]] = k ) // 定义:h[i] = height[ rank[i] ]
            for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++); //根据 h[i] >= h[i-1]-1 来优化计算height过程
    }
    char str[maxn];
    void work() {
        int lenstr = strlen(str);
        for (int i = 0; i < lenstr; ++i) r[i] = str[i];
        r[lenstr] = 0;
        dc3(r, sa, lenstr + 1, 128);
        calheight(r, sa, lenstr);
        int t = lenstr - height[rank[0]];
        if (t == lenstr || lenstr % t != 0) {
            printf("1
    ");
        } else {
            for (int i = t; i < lenstr; i += t) {
                for (int j = 0; j < t; ++j) {
                    if (str[j] != str[i + j]) {
                        printf("1
    ");
                        return;
                    }
                }
            }
            printf("%d
    ", lenstr / t);
        }
    }
    
    int main() {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        while (scanf("%s", str) != EOF) {
            if (str[0] == '.') break;
            work();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    eclipse中文乱码问题解决方案
    修改Tomcat的JDK目录
    Tomcat 5.5 修改服务器的侦听端口
    HTML DOM教程 27HTML DOM Button 对象
    HTML DOM教程 24HTML DOM Frameset 对象
    Navicat for MySQL v8.0.27 的注册码
    HTML DOM教程 25HTML DOM IFrame 对象
    Tomcat 5.5 的下载和安装
    android manifest相关属性
    ubuntu10.04 下 eclipse 小结
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5980449.html
Copyright © 2020-2023  润新知