kuangbin带你飞 后缀数组 题解

2份模板 DC3 。 空间复杂度O3N 时间复杂度On

#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 300010;
const int MAXM = 100010;
char input[MAXM];
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXM][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}
View Code


倍增 空间复杂度ON,时间复杂度ONLOGN

RMQ,LCP还有没测试过!

int sa[MAXN],r[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];
int Rank[MAXN],height[MAXN];

void build_sa(int s[],int n,int m)
{
    int i,j,p,*x = t1,*y = t2;
    for(i = 0 ; i < m ; i++) c[i] = 0;
    for(i = 0 ; i < n ; i++) c[x[i] = s[i]]++;
    for(i = 1 ; i < m ; i++) c[i] += c[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--c[x[i]]] = i;
    for(j = 1 ; j <= n ; j <<= 1)
    {
        p=0;
        for(i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < m ; i++) c[i] = 0;
        for(i = 0 ; i < n ; i++) c[x[y[i]]]++;
        for(i = 1 ; i < m ; i++) c[i]+=c[i-1];
        for(i = n - 1 ; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x,y);
        p = 1;
        x[sa[0]] = 0;
        for(i = 1 ; i < n ; i++)
            x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j] ? p - 1 : p++;
        if(p >= n)break;
        m = p;
    }
}

void getHeight(int s[],int n)
{
    int i,j,k = 0;
    for(i = 0;i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0;i < n ; i++)
    {
        if(k)k--;
        j = sa[Rank[i] - 1];
        while(s[i + k] == s[j + k])k++;
        height[Rank[i]] = k;
    }
}
/*
int mm[MAXN];
int best[20][MAXN];
void initRMQ(int n)
{
    mm[0] = -1;
    for(int i = 1 ; i <= n ;i++)
        mm[i] = ((i & (i - 1)) == 0)?mm[i - 1] + 1:mm[i - 1];
    for(int i = 1 ; i <=n ; i++) best[0][i] = i;
    for(int i = 1 ; i <=mm[n] ; i++)
        for(int j = 1 ; j + (1 << i) - 1 <= n ; j++)
        {
            int a=best[i - 1][j];
            int b=best[i - 1][j + (1 << (i - 1))];
            if(height[a] < height[b]) best[i][j] = a;
            else best[i][j] = b;
        }
}

int askRMQ(int a,int b)
{
    int t;
    t=mm[b - a + 1];
    b -= (1 << t) - 1;
    a = best[t][a];b = best[t][b];
    return height[a]<height[b] ? a : b;
}
int lcp(int a,int b)
{
    a = Rank[a];b = Rank[b];
    if(a > b)swap(a,b);
    return height[askRMQ(a + 1,b)];
}
*/
View Code


POJ 1743 Musical Theme

复制一波题意:

题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。“主题”是整个音符序列的一个子串,它需要满足如下条件:

    1.长度至少为5个音符。

    2.在乐曲中重复出现。(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值)

    3.重复出现的同一主题不能有公共部分。

首先构造差分序列,二分+height分段。至于不能重叠维护每一段最大值最小值。判断是否重叠即可

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 70010;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXN][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}
int num[MAXN];
int N;

bool judge(int mid)
{
    int MIN = INF,MAX = -1;
    int cas = 2;
    while (true)
    {
        while (cas <= N && height[cas] < mid) cas++;
        if (cas > N) break;
        MIN = sa[cas - 1];
        MAX = sa[cas - 1];
        while (cas <= N && height[cas] >= mid)
        {
            MIN = min(sa[cas],MIN);
            MAX = max(sa[cas],MAX);
            cas++;
        }
        if (MAX - MIN >= mid) return true;
    }
    return false;
}

int main()
{
    while (scanf("%d",&N) != EOF)
    {
        if (N == 0) break;
        for (int i = 0 ; i < N ; i++)
            scanf("%d",&num[i]);
        if (N < 10)
        {
            puts("0");
            continue;
        }
        N--;
        for (int i = 0 ; i < N ; i++)
        {
            num[i] = num[i + 1] - num[i] + 89;
        }
        num[N] = 0;
        dc3(num,sa,N + 1,256);
        calheight(num,sa,N);
       // for (int i = 0 ; i < N ; i++)
          //  printf("%d ",height[i]); putchar('
');
        int L = 4,R = N / 2 + 10;
        int ans = -1;
        while (L <= R)
        {
            int mid = (L + R) / 2;
            if (judge(mid))
            {
                ans = mid;
                L = mid + 1;
            }
            else R = mid - 1;
        }
        if (ans != -1)   printf("%d
",ans + 1);
        else puts("0");
    }
    return 0;
}
View Code

POJ 3261 Milk Patterns

可重叠至少出现K次最长子串

二分+height分段

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 70010;
const int MAXM = 70010;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int N;
int dp[MAXM][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}

int K;
int num[MAXN];

bool judge(int mid)
{
    int cas = 2,cnt = 0;
    while (true)
    {
        while (cas <= N && height[cas] < mid) cas++;
        if (cas > N) break;
        int cnt = 1;
        while (cas <= N && height[cas] >= mid)
        {
            cas++;
            cnt++;
        }
        if (cnt >= K) return true;
    }
    return false;
}

int main()
{
    while (scanf("%d%d",&N,&K) != EOF)
    {
        for (int i = 0 ; i < N ; i++)
            scanf("%d",&num[i]);
        for (int i = 0 ; i < N ; i++)
            num[i]++;
        num[N] = 0;
        dc3(num,sa,N + 1,20010);
        calheight(num,sa,N);
        int ans = -1;
        //for (int i = 0 ; i < N ; i++)
         //   printf("%d ",height[i]);putchar('
');
        int L = 0,R = 20010;
        while (L <= R)
        {
            int mid = (L + R) / 2;
            if (judge(mid))
            {
                L = mid + 1;
                ans = mid;
            }
            else R = mid - 1;
        }
        printf("%d
",ans);
    }
    return 0;
}
View Code

 SPOJ DISUBSTR DISUBSTR - Distinct Substrings

不重复的子串的个数

//所有子串都是某个后缀的前缀,那么对于每一个后缀,使他的起始位置为sa[i],那么它对答案的贡献是n - sa[i];
        //然而还有重复的。这个sa[i]与sa[i - 1]的LCP是height[i],那么说明sa[i -1]也有对应height个后缀已经计入答案,
        //所以实际对答案的贡献是N - sa[i] - height[i];
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 10010;
const int MAXM = 10010;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int N;
int dp[MAXM][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}

int num[MAXN];
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%s",str);
        N = strlen(str);
        for (int i = 0 ; i < N ; i++) num[i] = str[i];
        num[N] = 0;
        da(num,sa,N + 1,256);
        calheight(num,sa,N);
       // for (int i = 0 ; i <= N ; i++) printf("%d ",height[i]);puts("");
       //for (int i = 1 ; i <= N ; i++) printf("%d ",sa[i]); putchar('
');
        int ret = 0;
        for (int i = 1 ; i <= N ; i++) ret += N - sa[i] - height[i];
        //所有子串都是某个后缀的前缀,那么对于每一个后缀,使他的起始位置为sa[i],那么它对答案的贡献是n - sa[i];
        //然而还有重复的。这个sa[i]与sa[i - 1]的LCP是height[i],那么说明sa[i -1]也有对应height个后缀已经计入答案,
        //所以实际对答案的贡献是N - sa[i] - height[i];
        printf("%d
",ret);
    }
    return 0;
}
View Code

SPOJ SUBST1 SUBST1 - New Distinct Substrings

通上一题,只是变化了数据大小

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 150010;
const int MAXM = 150010;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int N;
int dp[MAXM][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}

int num[MAXN];
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%s",str);
        N = strlen(str);
        for (int i = 0 ; i < N ; i++) num[i] = str[i];
        num[N] = 0;
        da(num,sa,N + 1,256);
        calheight(num,sa,N);
        //for (int i = 1 ; i <= N ; i++) printf("%d ",height[i]);puts("");
        //for (int i = 1 ; i <= N ; i++) printf("%d ",sa[i]); putchar('
');
        int ret = 0;
        for (int i = 1 ; i <= N ; i++) ret += N - sa[i] - height[i];
        //所有子串都是某个后缀的前缀,那么对于每一个后缀,使他的起始位置为sa[i],那么它对答案的贡献是n - sa[i];
        //然而还有重复的。这个sa[i]与sa[i - 1]的LCP是height[i],那么说明sa[i -1]也有对应height个后缀已经计入答案,
        //所以实际对答案的贡献是N - sa[i] - height[i];
        printf("%d
",ret);
    }
    return 0;
}
View Code

POJ 2406 Power Strings
找最小循环节

KMP经典题,后缀数组我写额MLE了。。

KMP_AC

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define MAXN 3000010
int Next[MAXN],len;
char str[MAXN];
void kmp_pre()
{
    int i, j;
    j = Next[0] = - 1;
    i = 0;
    while (i < len)
    {
        while (j != -1 && str[i] != str[j]) j = Next[j];
        Next[++i] = ++j;
    }
}
int main()
{
    while (scanf("%s",str) != EOF)
    {
        if (str[0] == '.') break;
        len = strlen(str);
        kmp_pre();
        //for (int i = 0 ; i <= len ; i++) printf("next[%d] = %d
",i,next[i]);
       // putchar('
');
        if (len % (len - Next[len]) == 0) printf("%d
",len / (len - Next[len]) );
        else printf("%d
",1);

    }
    return 0;
}
View Code

MLE 也存下。没想着要去压他

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 1000010;
const int MAXM = 1000010;
const int INF = 0x3f3f3f3f;
int t1[MAXN],t2[MAXN],c[MAXN];
int Rank[MAXN],height[MAXN];
char str[MAXN];
int r[MAXN],sa[MAXN],N;
bool cmp(int *r,int a,int b,int l)
{
    return r[a] == r[b] && r[a + 1] == r[b + 1];
}

void da(int str[],int sa[],int Rank[],int height[],int n,int m)
{
    int i,j,p,*x = t1,*y = t2;
    for (int i = 0 ; i < m ; i++) c[i] = 0;
    for (int i = 0 ; i < n ; i++) c[x[i] = str[i]]++;
    for (int i = 1 ; i < m ; i++) c[i] += c[i - 1];
    for (int i = n - 1 ; i >= 0 ; i--) sa[--c[x[i]]] = i;
    for (int j = 1 ; j <= n ; j <<= 1)
    {
        p = 0;
        for (i = n - j ; i < n ; i++) y[p++] = i;
        for (i = 0 ; i < n ; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
        for (i = 0 ; i < m ; i++) c[i] = 0;
        for (i = 0 ; i < n ; i++) c[x[y[i]]]++;
        for (i = 1 ; i < m ; i++) c[i] += c[i - 1];
        for (i = n - 1 ; i >= 0 ; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x,y);
        p = 1;
        x[sa[0]] = 0;
        for (i = 1 ; i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
        if (p >= n) break;
        m = p;
    }
    n--;
    int k = 0;
    for (i = 0 ; i <= n ; i++) Rank[sa[i]] = i;
    for (i = 0 ; i < n ; i++)
    {
        if (k) k--;
        j = sa[Rank[i] - 1];
        while (str[i + k] == str[j + k]) k++;
        height[Rank[i]] = k;
    }
}


int RMQ[MAXN];
int mm[MAXN];
int best[25][MAXN];

void initRMQ(int n)
{
    mm[0] = -1;
    for (int i = 1 ; i <= n ; i++)
        mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
    for (int i = 1 ; i <= n ; i++) best[0][i] = i;
    for (int i = 1 ; i <= mm[n] ; i++)
        for (int j = 1 ; j + (1 << i) - 1 <= n ; j++)
    {
        int a = best[i - 1][j];
        int b = best[i - 1][j + (1 << (i - 1))];
        if (RMQ[a] < RMQ[b]) best[i][j] = a;
        else best[i][j] = b;
    }
}

int askrmq(int a,int b)
{
    int t;
    t = mm[b - a + 1];
    b -= (1 << t) - 1;
    a = best[t][a];
    b = best[t][b];
    return RMQ[a] < RMQ[b] ? a : b;
}

int lcp(int a,int b)
{
    a = Rank[a];
    b = Rank[b];
    if (a > b) swap(a,b);
    return height[askrmq(a + 1,b)];
}


bool judge(int length)
{
    if (N % length) return false;
    int tmp = lcp(0,0 + length);
   // printf("%d %d 
",length,1 + length);
   // printf("%d %d
",length,tmp);
    if (tmp == N - length) return true;
    return false;
}

int main()
{
    while (scanf("%s",str) != EOF)
    {
        if (str[0] == '.') break;
        N = strlen(str);
        for (int i = 0 ; i < N ; i++) r[i] = str[i];
        r[N] = 0;
        da(r,sa,Rank,height,N + 1,256);
        initRMQ(N);
        int ret = 1;
        for (int i = 1 ; i <= N / 2 + 1 ; i++)
        {
            if(judge(i))
            {
                ret = N / i;
               // printf("%d
",i);
                break;
            }
        }
        printf("%d
",ret);
    }
    return 0;
}
View Code

SPOJ SPOJ REPEATS REPEATS - Repeats
论文里的题目:参照后缀数组处理字符串的有力工具。

论文里没提到的就是有一种情况下,可以由于不是整除的匹配可以在向左或向右是的重复次数再加1

算法分析:
先穷举长度 L,然后求长度为 L 的子串最多能连续出现几次。首先连续出现
1 次是肯定可以的,所以这里只考虑至少 2 次的情况。假设在原字符串中连续出
现 2 次,记这个子字符串为 S,那么 S 肯定包括了字符 r[0], r[L], r[L*2],
r[L*3], ……中的某相邻的两个。所以只须看字符 r[L*i]和 r[L*(i+1)]往前和
往后各能匹配到多远,记这个总长度为 K,那么这里连续出现了 K/L+1 次。最后
看最大值是多少。如图 7 所示。
穷举长度 L 的时间是 n,每次计算的时间是 n/L。所以整个做法的时间复杂
度是 O(n/1+n/2+n/3+……+n/n)=O(nlogn)。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 200010;
const int MAXM = 100010;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXM][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}

int calcu(int n)
{
    int ret = 1;
    for (int l = 1 ; l < n ; l++)
    {
        for (int i = 0 ; i + l < n ; i += l)
        {
            int length = rmq(i,i + l);
            int tmp = length / l + 1;
            int left = i - (l - length % l);
            if (left >= 0 && length % l && rmq(left,left + l) >= length)
                tmp++;
            ret = max(ret,tmp);
        }
    }
    return ret;
}
char input[10];
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        int N;
        scanf("%d",&N);
        for (int i = 0 ; i < N ; i++)
        {
            scanf("%s",input);
            r[i] = (int)input[0] + 1;
        }
        r[N] = 0;
        dc3(r,sa,N + 1,256);
        calheight(r,sa,N);
        RMQ_init(N,height);
        printf("%d
",calcu(N));
    }
    return 0;
}
View Code

POJ 3693 Maximum repetition substring

通上一题

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 300010;
const int MAXM = 100010;
char input[MAXM];
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXM][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}

int ans[MAXM],tot;
pair<int,int>output;
int calcu(int n)
{
    int ret = 0;
    for (int l = 1 ; l < n ; l++)
    {
        for (int i = 0 ; i + l < n ; i += l)
        {
            int length = rmq(i,i + l);
            int tmp = length / l + 1;
            int left = i - (l - length % l);
            if (left >= 0 && length % l && rmq(left,left + l) >= length)
                tmp++;
            if (tmp == ret)
            {
                ans[tot++] = l;
            }
            else if (tmp > ret)
            {
                tot = 0;
                ans[tot++] = l;
                ret = tmp;
            }
        }
    }
    return ret;
}

int main()
{
    //freopen("sample.txt","r",stdin);
    int kase = 1,N;
    while (scanf("%s",input) != EOF)
    {
        if (input[0] == '#') break;
        N = strlen(input);
        for (int i = 0 ; i < N ; i++)
            r[i] = input[i];
        r[N] = 0;
        dc3(r,sa,N + 1,256);
        calheight(r,sa,N);
        RMQ_init(N,height);
        int maxcnt = calcu(N);
        tot = unique(ans,ans + tot) - ans;
        printf("Case %d: ",kase++);
        bool flag = false;
        for (int i = 1 ; i <= N && !flag ; i++)
        {
            for (int j = 0 ; j < tot ; j++)
            {
                int length = ans[j];
                if (rmq(sa[i],sa[i] + length) >= (maxcnt - 1) * length)
                {
                    output.first = sa[i];
                    output.second = sa[i] + maxcnt * length - 1;
                    flag = true;
                }
            }
        }
        for (int i = output.first ; i <= output.second ; i++)
            printf("%c",input[i]);
        putchar('
');
    }
    return 0;
}
View Code

POJ 2774 Long Long Message

2个串的最长公共子串

水体,拼串后缀数组直接做

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 600010;
const int MAXM = 200010;
char input[MAXM];
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[MAXN];
int dp[MAXM][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}


int posmid;

int calcu(int N)
{
    int ret = 0;
    for (int i = 3 ; i <= N ; i++)
    {
        int l = sa[i - 1],r = sa[i];
        if (l > r) swap(l,r);
        if (l <= posmid && r <= posmid) continue;
        if (r >= posmid && l >= posmid) continue;
        ret = max(ret,height[i]);
    }
    return ret;
}
int main()
{
    int N,cas;
    while (scanf("%s",str) != EOF)
    {
        cas = 0;
        int len = strlen(str);
        for (int i = 0 ; i < len ; i++)
            r[cas++] = str[i];
        posmid = cas;
        r[cas++] = 1;
        scanf("%s",str);
        len = strlen(str);
        for (int i = 0 ; i < len ; i++)
            r[cas++] = str[i];
        r[cas] = 0;
       // for (int i = 0 ; i <= cas ; i++)
        //    printf("%d ",r[i]); putchar('
');
        N = cas;
        dc3(r,sa,N + 1,256);
        calheight(r,sa,N);
        printf("%d
",calcu(N));
    }
    return 0;
}
View Code

POJ 3415 Common Substrings

这个题也是论问题,很难。尤其是单调栈哪里

这里论文内容

给定两个字符串 A 和 B,求长度不小于 k 的公共子串的个数(可以相同)。
样例 1:
A=“xx”,B=“xx”,k=1,长度不小于 k 的公共子串的个数是 5。
样例 2:
A = “aababaa”,B = “abaabaa”,k=2,长度不小于 k 的公共子串的个数是22。
算法分析:
基本思路是计算 A 的所有后缀和 B 的所有后缀之间的最长公共前缀的长度,
把最长公共前缀长度不小于 k 的部分全部加起来。先将两个字符串连起来,中间
用一个没有出现过的字符隔开。按 height 值分组后,接下来的工作便是快速的
统计每组中后缀之间的最长公共前缀之和。扫描一遍,每遇到一个 B 的后缀就统
计与前面的 A 的后缀能产生多少个长度不小于 k 的公共子串,这里 A 的后缀需要
用一个单调的栈来高效的维护。然后对 A 也这样做一次。具体的细节留给读者思
考。

首先对于A,B串的2个后缀,他们对答案的贡献是LCP - K + 1,前提是LCP >= K;

如果你直接暴力那么复杂度就是N*N*LOGN;

所以要用单调栈优化。这里我一直想不出扎弄。看了别人的代码半天看懂了。

首先第一步是分布统计,第一次同意每一个B串前面A串与之的LCP额答案。第二次反过来。2次答案和就是我们要的

那么问题就是每一步的同意,维护一个变量tot这个就是对答案的影响

注意到2个串的LCP就是他们所在RANK之间的height 的最小值。仔细想一下。对于每一个B串,他与前面的A串与他之间的LCP是单调不减的。于是你

可以维护处这个单调递增额栈。里面是height值和这个height对后边几个穿的影响;这里说起来麻烦,举例子说也很麻烦。

大致距离一下有5个后缀,ABCDE,对应就是4个height值我认为他是h1,h2,h3,h4相应的就是A-B LCP,B-C LCP 。。。。

如果有H1 < H4 < H2 < H3 ,注意这里我不讨论那个后缀是A串后缀那个后缀是B串后缀了。虽然仍然很重要。

我们从左向右扫的时候有。H1,H2,H3一直单调递增很简单处理。到这里答案就是lcp(a,b) + lcp(c,a) + lcp(c,b) + lcp(d,a) + lcp(d,b) + lcp(d,c) = h1 + h1 + h1 + h2 + h2 + h3;

站内统计的就是他所"支配的"A串个数,遇到H4的时候就要有出栈,有了这个H4。之后所有的B串与C,D位置的LCP至少不会由H2,H3来管,可能与H4相关,我们把H2,H3出栈,H4入展

同事要维护tot,就是栈内所有元素的价值,这个不太好说明白。关键就是这个量。具体看代码把

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 600010;
const int MAXM = 200010;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
int dp[MAXM][25];
int N;
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}

char input[MAXM];
int cas,K,posmid;
int Stack[MAXN][2],top;

int main()
{
    while (scanf("%d",&K) != EOF)
    {
        if (K == 0) break;
        cas = 0;
        scanf("%s",input);
        int len = strlen(input);
        posmid = len;
        for (int i = 0 ; i < len ; i++)
            r[cas++] = input[i];
        r[cas++] = 1;
        scanf("%s",input);
        len = strlen(input);
        for (int i = 0 ; i < len ; i++)
            r[cas++] = input[i];
        r[cas] = 0;
        N = cas;
       // for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]); putchar('
');
        LL ret = 0,tot = 0;
        top = 0;
        dc3(r,sa,N + 1,256);
        calheight(r,sa,N);
        for (int i = 1 ; i <= N ; i++)
        {
            if (height[i] < K)
            {
                tot = 0;
                top = 0;
            }
            else
            {
                int num = 0;
                if (sa[i - 1] < posmid)
                {
                    num++;
                    tot += (LL)(height[i] - K + 1);
                }
                while (top > 0 && height[i] <= Stack[top - 1][0])
                {
                    top--;
                    tot -= (LL)Stack[top][1] * (Stack[top][0] - height[i]);
                    num += Stack[top][1];
                }
                Stack[top][0] = height[i];
                Stack[top++][1] = num;
                if (sa[i] > posmid) ret += (LL)tot;
            }
        }
        tot = 0;
        top = 0;
        for (int i = 1 ; i <= N ; i++)
        {
            if (height[i] < K)
            {
                tot = 0;
                top = 0;
            }
            else
            {
                int num = 0;
                if (sa[i - 1] > posmid)
                {
                    num++;
                    tot += (LL)(height[i] - K + 1);
                }
                while (top > 0 && height[i] <= Stack[top - 1][0])
                {
                    top--;
                    tot -= (LL)Stack[top][1] * (Stack[top][0] - height[i]);
                    num += Stack[top][1];
                }
                Stack[top][0] = height[i];
                Stack[top++][1] = num;
                if (sa[i] < posmid) ret += (LL)tot;
            }
        }
        printf("%I64d
",ret);
    }
    return 0;
}
View Code

POJ 3294 Life Forms

题意:求大于k/2个字符串中含有的最长公共子串

二分+height分段+判断

如何输出参照下代码吧

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 310010;
const int MAXM = 100010;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[2010];
int dp[MAXM][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a] == r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}

int cas,N;
vector<int> ret,tmp;
int pos[1010],cnt,num;
int comp[MAXN],tot;

bool judge(int mid)
{
    int step = 1;
    tot = 0;
    while (true)
    {
        int cnt = 0;
        while (step <= N && height[step] < mid) step++;
        if (step > N) break;
        tot = 0;
        while (height[step] >= mid)
        {
            int lft = sa[step - 1];
            int rht = sa[step];
            int poslft = lower_bound(pos,pos + num,lft) - pos;
            int posrht = lower_bound(pos,pos + num,rht) - pos;
            comp[tot++] = poslft;
            comp[tot++] = posrht;
            step++;
        }
        sort(comp,comp + tot);
        tot = unique(comp,comp + tot) - comp;
        if (tot % 2 == 0 && tot > num / 2)
            return true;
        else if (tot % 2 == 1 && tot >= (num + 1) / 2)
            return true;
    }
    return false;
}

void output(int length)
{
    int step = 1;
    while (true)
    {
        while (step <= N && height[step] < length) step++;
        if (step > N) break;
        tot = 0;
        int st = step;
        while (step <= N && height[step] >= length)
        {
            int lft = sa[step - 1];
            int rht = sa[step];
            int poslft = lower_bound(pos,pos + num,lft) - pos;
            int posrht = lower_bound(pos,pos + num,rht) - pos;
            comp[tot++] = poslft;
            comp[tot++] = posrht;
            step++;
        }
        sort(comp,comp + tot);
        tot = unique(comp,comp + tot) - comp;
        if ((tot % 2 == 0 && tot > num / 2) || (tot % 2 == 1 && tot >= (num + 1) / 2))
        {
            int srt = sa[st - 1];
            for (int i = srt ,j = 0 ; j < length ; j++,i++)
                printf("%c",r[i] - 100);
            putchar('
');
        }
    }
}

int main()
{
   // freopen("sample.txt","r",stdin);
    bool first = true;
    while (scanf("%d",&num) != EOF)
    {
        if (num == 0) break;
        if (first) first = false;
        else puts("");
        cas = 0;
        int step = 0;
        int tmp = 0;
        for (int i = 0 ; i < num ; i++)
        {
            scanf("%s",str);
            int len = strlen(str);
            tmp = max(len,tmp);
            for (int j = 0 ; j < len ; j++)
                r[cas++] = str[j] + 100;
            pos[i] = cas;
            r[cas++] = step;
            step++;
        }
        cas--;
        N = cas;
        //for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]); putchar('
');
        //for (int i = 0 ; i < num ; i++) printf("%d ",pos[i]); putchar('
');
        dc3(r,sa,N + 1,256);
        calheight(r,sa,N);
        int l = 1 ,r = tmp,ans = 0;
        ret.clear();
        while (l <= r)
        {
            int mid = (l + r) / 2;
            if (judge(mid))
            {
                l = mid + 1;
                ans = mid;
            }
            else r = mid - 1;
        }
       // printf("%d
",ans);
        if (ans == 0) puts("?");
        else
            output(ans);
    }
    return 0;
}
View Code

SPOJ PHRASES PHRASES - Relevant Phrases of Annihilation

在每个串都至少出现2次

二分判断时每个分串计算最大最小位置值既可以了。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 310010;
const int MAXM = 100010;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[20010];
int dp[MAXM][25];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a] == r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}

int cas,N,num;
int pos[20];
int MIN[20],MAX[20];

bool judge(int mid)
{
    int step = 1;
    while (true)
    {
        while (step <= N && height[step] < mid) step++;
        if (step > N) break;
        for (int i = 0 ; i < 20 ; i++)
        {
            MIN[i] = INF;
            MAX[i] = -INF;
        }
        while (step <= N && height[step] >= mid)
        {
            int lft = sa[step - 1];
            int rht = sa[step];
            int poslft = lower_bound(pos,pos + num,lft) - pos;
            int posrht = lower_bound(pos,pos + num,rht) - pos;
            MIN[poslft] = min(MIN[poslft],lft);
            MAX[poslft] = max(MAX[poslft],lft);
            MIN[posrht] = min(MIN[posrht],rht);
            MAX[posrht] = max(MAX[posrht],rht);
            step++;
        }
        bool flag = false;
        for (int i = 0 ; i < num ; i++)
        {
            //printf("%d %d
",MIN[i],MAX[i]);
            if (MIN[i] == INF || MAX[i] == -INF  || MAX[i] <= MIN[i] + mid - 1)
            {
                flag = true;
                break;
            }
        }
       // putchar('
');
        if (!flag) return true;
    }
    return false;
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&num);
        cas = 0;
        int step = 0;
        for (int i = 0 ; i < num ; i++)
        {
            scanf("%s",str);
            int len = strlen(str);
            for (int j = 0 ; j < len ; j++)
                r[cas++] = str[j] + 20;
            pos[i] = cas;
            r[cas++] = step++;
        }
        cas--;
        N = cas;
        dc3(r,sa,N + 1,256);
        calheight(r,sa,N);
       // for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]); putchar('
');
       // for (int i = 0 ; i < num ; i++) printf("%d ",pos[i]); putchar('
');
        int L = 0,R = 10010,ans = 0;
        while (L <= R)
        {
            int mid = (L + R) / 2;
            if (judge(mid))
            {
                L = mid + 1;
                ans = mid;
            }
            else R = mid - 1;
        }
        //printf("%d
",judge(2));
        printf("%d
",ans);
    }
    return 0;
}
View Code

POJ 1226 substrings

题意:给定n个串,求一个最大子串长度,使得它或者它的逆向串在每个串中出现

每个串正向逆向构造出来然后所有串拼到一起 。其他的大致一样

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 61010;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[105],res[105];
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a] == r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}
/*
void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}
*/

int cas,N,num;
int belong[20010];
bool vis[110];

bool judge(int mid)
{
    int step = 1;
    while(true)
    {
        while (step <= N && height[step] < mid) step++;
        if (step > N) break;
        memset(vis,false,sizeof(vis));
        while (step <= N && height[step] >= mid)
        {
            vis[belong[sa[step - 1]]] = true;
            vis[belong[sa[step]]] = true;
            step++;
        }
        bool found = true;
        for (int i = 0 ; i < num ; i++)
        {
            if (!vis[i])
            {
                found = false;
                break;
            }
        }
        if (found) return true;
    }
    return false;
}

int main()
{
   // freopen("sample.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&num);
        cas = 0;
        int step = 0;
        for (int i = 0 ; i < num ; i++)
        {
            scanf("%s",str);
            int len = strlen(str);
            for (int j = 0 ; j < len ; j++)
            {
                belong[cas] = i;
                if (islower(str[j]))
                {
                    r[cas++] = str[j] - 'a' + 205;
                }
                else r[cas++] = str[j] - 'A' + 232;
            }
            belong[cas] = -1;
            r[cas++] = step++;
            for (int k = 0 , j = len - 1 ; j >= 0 ; k++,j--)
                res[k] = str[j];
            res[len] = '';
            for (int j = 0 ; j < len ; j++)
            {
                belong[cas] = i;
                if (islower(res[j])) r[cas++] = res[j] - 'a' + 205;
                else r[cas++] = res[j] - 'A' + 232;
            }
            belong[cas] = -1;
            r[cas++] = step++;
        }
        cas--;
        N = cas;
       // for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]);  putchar('
');
       // for (int i = 0 ; i <= N ; i++) printf("%d ",belong[i]); putchar('
');
        dc3(r,sa,N + 1,270);
        calheight(r,sa,N);
        int L = 1,R = 100;
        int ans = 0;
        while (L <= R)
        {
            int mid = (L + R) / 2;
            if (judge(mid))
            {
                ans = mid;
                L = mid + 1;
            }
            else R = mid - 1;
        }
        printf("%d
",ans);
    }
    return 0;
}
View Code

UVA 11475 Extend to Palindrome

在末尾添加最少的字符使得串回文。

将串反过来。

以反串为模式串,原本串有主串,KMP找最大匹配长度。其他的补足输出就可

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 100010;
char str[MAXN],rev[MAXN];
int fail[MAXN];

void kmp_pre(char x[],int m,int fail[])
{
    int i,j;
    j = fail[0] = -1;
    i = 0;
    while (i < m)
    {
        while (j != -1 && x[i] != x[j]) j = fail[j];
        fail[++i] = ++j;
    }
}

int kmp_find(char x[],int m,char y[],int n)
{
    int i,j;
    i = j = 0;
    while(i < n)
    {
        while (j != -1 && y[i] != x[j]) j = fail[j];
        i++;
        j++;
        if (j >= m) return j;
    }
    return j;
}

int main()
{
    while (scanf("%s",str) != EOF)
    {
        int len = strlen(str);
        for (int j = len - 1 , i = 0 ; i < len ; j--,i++)
            rev[i] = str[j];
        rev[len] = '';
       // printf("%s
%s
",str,rev);
        kmp_pre(rev,len,fail);
        int pos = kmp_find(rev,len,str,len);
        printf("%s%s
",str,rev + pos);
    }
    return 0;
}
View Code

POJ 3581 Sequence
http://blog.163.com/just_gogo/blog/static/1914390652011823103842787/

将原本的串分成三段,每段反过来厚字典序最小。参照了别人的。真心蠢啊。

解题思路:
其实这个思路是在discuss里面看到的;用的后缀数组。。
原理很简单:把数子按逆序求一次后缀数组(sa数组),然后里面最小的那个就可以直接输出了(当然为了满足分成3份,所以最小的那个sa[min]要>=2这里是从0开始的);
然后将剩下的数字复制一遍贴在剩下的数字后面(可能有点拗口,比如剩下的数字为:3 2 4那么复制一下在贴在 后面就成了3 2 4 3 2 4);
然后再对这个求一次后缀数组;这样就可以输出了最小(sa[min]>0)的那一串数字了。。再最后就输出剩下的那些数字了;
刚开始的时候觉得没有必要将剩下的数字复制一片贴在剩下的数字后面,所以wa了很多次。。。
最后在discuss里面看见一组数据:
9
8 4 -1 5 0 5 0 2 3
第一步:
3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8
第二步
3 2 0 5 0 5(开始的时候我并没有复制一遍) 对应输出:0 5
第三步
3 2 0 5    对应输出: 3 2 0 5
可以看见这样做是不对的。。
必须要将剩下的字符串复制一遍贴在后面,然后再来求后缀数组。。。
正解:
第一步:
3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8
第二步
3 2 0 5 0 5 3 2 0 5 0 5 对应输出: 0 5 0 5;
第三步
3 2 对应输出:3 2;

最后值得注意的是此题还要用离散化。。因为并没有告诉我们输入的数据有多大。。。。。

代码

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 620010;
const int INF = 0x3f3f3f3f;
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
char str[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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[wv[i]]] = a[i];
}

void dc3(int *r,int *sa,int n,int m)
{
    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++];
}


int cmp(int *r,int a,int b,int l)
{return r[a ]== r[b] && r[a + l] == r[b + l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x = wa,*y = wb,*t;
    for(i = 0 ; i < m ; i++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1;i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(int *r,int *sa,int n)
{
    int i,j,k = 0;
    for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0 ; i < n ; height[Rank[i++]] = k)
    for(k ? k--:0,j = sa[Rank[i] - 1] ;r[i + k]==r[j + k];k++);
}
/*
int RMQ[MAXN];
int mm[MAXN];
int best[20][MAXN];

void initRMQ(int n)
{
    mm[0] = -1;
    for (int i = 1 ; i <= n ; i++)
        mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
    for (int i = 1 ; i <= n ; i++) best[0][i] = i;
    for (int i = 1 ; i <= mm[n] ; i++)
        for (int j = 1 ; j + (1 << i) - 1 <= n ; j++)
    {
        int a = best[i - 1][j];
        int b = best[i - 1][j + (1 << (i - 1))];
        if (RMQ[a] < RMQ[b]) best[i][j] = a;
        else best[i][j] = b;
    }
}

int askrmq(int a,int b)
{
    int t;
    t = mm[b - a + 1];
    b -= (1 << t) - 1;
    a = best[t][a];
    b = best[t][b];
    return RMQ[a] < RMQ[b] ? a : b;
}

int lcp(int a,int b)
{
    a = Rank[a];
    b = Rank[b];
    if (a > b) swap(a,b);
    return height[askRMQ(a + 1,b)];
}
*/

struct node
{
    int val;
    int newval;
    int id;
    friend bool operator < (const node &a,const node &b)
    {

        return a.val < b.val;
    }
}src[MAXN];
int N;

int cmp1(const node &a,const node &b)
{
    return a.id > b.id;
}

int main()
{
    scanf("%d",&N);
    for (int i = 0 ; i < N ; i++)
    {
        scanf("%d",&src[i].val);
        src[i].id = i + 1;
    }
    sort(src,src + N);
    src[0].newval = 1;
    for (int i = 1 ; i < N ; i++)
    {
        if (src[i].val == src[i - 1].val)
                src[i].newval = src[i - 1].newval;
        else src[i].newval = src[i - 1].newval + 1;
    }
    sort(src,src + N,cmp1);
    for (int i = 0 ; i < N ; i++)
        r[i] = src[i].newval;
    r[N] = 0;
    dc3(r,sa,N + 1,N + 10);
    int i;
    for(i = 1; i <= N && sa[i] <= 1 ; i++);
    int pos1 = sa[i];
    for (i = pos1 ; i < N ; i++) printf("%d
",src[i].val);
    for (i = 0 ; i < pos1 ; i++) src[i + pos1] = src[i];
    //for (i = 0 ; i < 2 * pos1 ; i++) printf("%d ",src[i].val); putchar('
');
    for (i = 0 ; i < 2 * pos1 ; i++) r[i] = src[i].newval;
    N = 2 * pos1;
    r[N] = 0;
    dc3(r,sa,N + 1,N + 10);
    int pos2;
    for (i = 1 ; i <= N && (!sa[i] || sa[i] >= N / 2) ; i++);
    pos2 = sa[i];
    for (i = pos2 ; i < N / 2 ; i++) printf("%d
",src[i].val);
    for (i = 0 ; i < pos2 ; i++) printf("%d
",src[i].val);
    return 0;
}
View Code

POJ 3450 Corporate Identity

每个串都有的最长的最小字典序的串

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 900100;
const int INF = 0x3f3f3f3f;
int sa[MAXN],r[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];
int Rank[MAXN],height[MAXN];

void build_sa(int s[],int n,int m)
{
    int i,j,p,*x = t1,*y = t2;
    for(i = 0 ; i < m ; i++) c[i] = 0;
    for(i = 0 ; i < n ; i++) c[x[i] = s[i]]++;
    for(i = 1 ; i < m ; i++) c[i] += c[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--c[x[i]]] = i;
    for(j = 1 ; j <= n ; j <<= 1)
    {
        p=0;
        for(i = n - j ; i < n ; i++) y[p++] = i;
        for(i = 0 ; i < n ; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(i = 0 ; i < m ; i++) c[i] = 0;
        for(i = 0 ; i < n ; i++) c[x[y[i]]]++;
        for(i = 1 ; i < m ; i++) c[i]+=c[i-1];
        for(i = n - 1 ; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x,y);
        p = 1;
        x[sa[0]] = 0;
        for(i = 1 ; i < n ; i++)
            x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j] ? p - 1 : p++;
        if(p >= n)break;
        m = p;
    }
}

void getHeight(int s[],int n)
{
    int i,j,k = 0;
    for(i = 0;i <= n ; i++) Rank[sa[i]] = i;
    for(i = 0;i < n ; i++)
    {
        if(k)k--;
        j = sa[Rank[i] - 1];
        while(s[i + k] == s[j + k])k++;
        height[Rank[i]] = k;
    }
}
/*
int mm[MAXN];
int best[20][MAXN];
void initRMQ(int n)
{
    mm[0] = -1;
    for(int i = 1 ; i <= n ;i++)
        mm[i] = ((i & (i - 1)) == 0)?mm[i - 1] + 1:mm[i - 1];
    for(int i = 1 ; i <=n ; i++) best[0][i] = i;
    for(int i = 1 ; i <=mm[n] ; i++)
        for(int j = 1 ; j + (1 << i) - 1 <= n ; j++)
        {
            int a=best[i - 1][j];
            int b=best[i - 1][j + (1 << (i - 1))];
            if(height[a] < height[b]) best[i][j] = a;
            else best[i][j] = b;
        }
}

int askRMQ(int a,int b)
{
    int t;
    t=mm[b - a + 1];
    b -= (1 << t) - 1;
    a = best[t][a];b = best[t][b];
    return height[a]<height[b] ? a : b;
}
int lcp(int a,int b)
{
    a = Rank[a];b = Rank[b];
    if(a > b)swap(a,b);
    return height[askRMQ(a + 1,b)];
}
*/

int num;
int N,cas;
bool vis[4010];
char str[210];
int belong[MAXN];
int ans[MAXN],tot;

bool judge(int mid)
{
    int step = 1;
    while (true)
    {
        while (step <= N && height[step] < mid) step++;
        if (step > N) break;
        memset(vis,false,sizeof(vis));
        while (step <= N && height[step] >= mid)
        {
            int lft = belong[sa[step - 1]];
            int rht = belong[sa[step]];
            vis[lft] = vis[rht] = true;
            step++;
        }
        bool flag = false;
        for (int i = 0 ; i < num ; i++)
        {
            if (!vis[i])
            {
                flag = true;
                break;
            }
        }
        if (!flag) return true;
    }
    return false;
}

int ret;
void output(int length)
{
    ret = INF;
    int step = 1;
    while (true)
    {
        while (step <= N && height[step] < length) step++;
        if (step > N) break;
        int Min = sa[step - 1];
        memset(vis,false,sizeof(vis));
        while (step <= N && height[step] >= length)
        {
            int lft = belong[sa[step - 1]];
            int rht = belong[sa[step]];
            vis[lft] = vis[rht] = true;
            step++;
        }
        bool flag = false;
        for (int i = 0 ; i < num ; i++)
        {
            if (!vis[i])
            {
                flag = true;
                break;
            }
        }
        if (!flag)
        {
            ret = Min;
            break;
        }
    }
    for (int i = 0,j = ret ; i < length ; i++,j++)
        printf("%c",r[j] - 4005);
    putchar('
');
}

int main()
{
    while (scanf("%d",&num) != EOF)
    {
        if (num == 0) break;
        cas = 0;
        int step = 0;
        for (int i = 0 ; i < num ; i++)
        {
            scanf("%s",str);
            int len = strlen(str);
            for (int j = 0 ; j < len ; j++)
            {
                belong[cas] = i;
                r[cas++] = str[j] + 4005;
            }
            belong[cas] = -1;
            r[cas++] = step;
            step++;
        }
        cas--;
        N = cas;

        build_sa(r,N + 1,5000);
        getHeight(r,N);
       // for (int i = 0 ; i <= N ; i++) printf("%d ",r[i]); puts("");
        int ans = 0,L = 1,R = 256;
        while (L <= R)
        {
            int mid = (L + R) / 2;
            if (judge(mid))
            {
                ans = mid;
                L = mid + 1;
            }
            else R = mid -1;
        }
       // printf("%d
",ans);
        if (ans == 0) puts("IDENTITY LOST");
        else
        {
            output(ans);
        }
    }
    return 0;
}
View Code

POJ 3080 Blue Jeans

数据太小了。直接KMP爆。直接裸爆都行

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 1000;
char str[MAXN],src[MAXN];
int fail[MAXN];
struct node
{
    char word[80];
    int length;
    friend bool operator < (const node &a,const node &b)
    {
        return a.length < b.length;
    }
}res[MAXN];

void kmp_pre(char x[],int m,int fail[])
{
    int i,j;
    j = fail[0] = -1;
    i = 0;
    while (i < m)
    {
        while (j != -1 && x[i] != x[j]) j = fail[j];
        fail[++i] = ++j;
    }
}

bool kmp_find(char x[],int m,char y[],int n)
{
    int i,j;
    i = j = 0;
    while(i < n)
    {
        while (j != -1 && y[i] != x[j]) j = fail[j];
        i++;
        j++;
        if (j >= m) return true;
    }
    return false;
}

int main()
{
    //freopen("sample.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while (T--)
    {
        int N;
        scanf("%d",&N);
        for (int i = 0 ; i < N ; i++)
        {
            scanf("%s",res[i].word);
            res[i].length = strlen(res[i].word);
        }
        sort(res,res + N);
        char tmp[110],cmp[110];
        int ret = 0;
        for (int l = 0 ; l < res[0].length ; l++)
        {
            for (int r = l ; r < res[0].length ; r++)
            {
                int leap = 0;
                for (int i = l ; i <= r ; i++)
                    tmp[leap++] = res[0].word[i];
                tmp[leap] = '';
                bool flag = false;
                kmp_pre(tmp,leap,fail);
                for (int i = 1 ; i < N ; i++)
                {
                    if (!kmp_find(tmp,leap,res[i].word,res[i].length))
                    {
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                {
                    if (r - l + 1 > ret)
                    {
                        ret = r - l + 1;
                        int step = 0;
                        for (int i = l ; i <= r ; i++)
                            cmp[step++] = res[0].word[i];
                        cmp[step] = '';
                    }
                    else if (r - l + 1 == ret)
                    {
                        if (strcmp(tmp,cmp) < 0) strcpy(cmp,tmp);
                    }
                }
            }
        }
        if (ret < 3) printf("no significant commonalities
");  
        else
        {
            printf("%s
",cmp);
        }
    }
    return 0;
}
View Code

POJ 2758 Checking the Text

我看HUST没人做。就不做了。汗!!

记到这里一旦哪天想做了呢

原文地址:https://www.cnblogs.com/Commence/p/4888181.html