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]);
}

倍增 空间复杂度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)];
}
*/

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(‘\n‘);
        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\n",ans + 1);
        else puts("0");
    }
    return 0;
}

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(‘\n‘);
        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\n",ans);
    }
    return 0;
}

 

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(‘\n‘);
        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\n",ret);
    }
    return 0;
}

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(‘\n‘);
        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\n",ret);
    }
    return 0;
}

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\n",i,next[i]);
       // putchar(‘\n‘);
        if (len % (len - Next[len]) == 0) printf("%d\n",len / (len - Next[len]) );
        else printf("%d\n",1);

    }
    return 0;
}

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 \n",length,1 + length);
   // printf("%d %d\n",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\n",i);
                break;
            }
        }
        printf("%d\n",ret);
    }
    return 0;
}

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\n",calcu(N));
    }
    return 0;
}

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(‘\n‘);
    }
    return 0;
}

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‘);
        N = cas;
        dc3(r,sa,N + 1,256);
        calheight(r,sa,N);
        printf("%d\n",calcu(N));
    }
    return 0;
}

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(‘\n‘);
        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\n",ret);
    }
    return 0;
}

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(‘\n‘);
        }
    }
}

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(‘\n‘);
        //for (int i = 0 ; i < num ; i++) printf("%d ",pos[i]); putchar(‘\n‘);
        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\n",ans);
        if (ans == 0) puts("?");
        else
            output(ans);
    }
    return 0;
}

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\n",MIN[i],MAX[i]);
            if (MIN[i] == INF || MAX[i] == -INF  || MAX[i] <= MIN[i] + mid - 1)
            {
                flag = true;
                break;
            }
        }
       // putchar(‘\n‘);
        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(‘\n‘);
       // for (int i = 0 ; i < num ; i++) printf("%d ",pos[i]); putchar(‘\n‘);
        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\n",judge(2));
        printf("%d\n",ans);
    }
    return 0;
}

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] = ‘\0‘;
            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(‘\n‘);
       // for (int i = 0 ; i <= N ; i++) printf("%d ",belong[i]); putchar(‘\n‘);
        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\n",ans);
    }
    return 0;
}

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] = ‘\0‘;
       // printf("%s\n%s\n",str,rev);
        kmp_pre(rev,len,fail);
        int pos = kmp_find(rev,len,str,len);
        printf("%s%s\n",str,rev + pos);
    }
    return 0;
}

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\n",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(‘\n‘);
    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\n",src[i].val);
    for (i = 0 ; i < pos2 ; i++) printf("%d\n",src[i].val);
    return 0;
}

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(‘\n‘);
}

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\n",ans);
        if (ans == 0) puts("IDENTITY LOST");
        else
        {
            output(ans);
        }
    }
    return 0;
}

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] = ‘\0‘;
                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] = ‘\0‘;
                    }
                    else if (r - l + 1 == ret)
                    {
                        if (strcmp(tmp,cmp) < 0) strcpy(cmp,tmp);
                    }
                }
            }
        }
        if (ret < 3) printf("no significant commonalities\n");
        else
        {
            printf("%s\n",cmp);
        }
    }
    return 0;
}

POJ 2758 Checking the Text

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

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

时间: 2024-10-26 19:00:38

kuangbin带你飞 后缀数组 题解的相关文章

Kuangbin 带你飞 数位DP题解

以前一直不知道该咋搞这个比较好. 感觉推起来那个数字好麻烦.后来有一种比较好的写法就是直接的DFS写法.相应的ismax表示当前位是否有限制. 数位DP也是有一种类似模版的东西,不过需要好好理解.与其他模版不同. 主要还是状态的定义 模版就不整理了.直接上题. 另外这里有一道题是数位DP+自动机的放到自动机里做 HDU 2089 不要62 基本的数位DP可以用来理解DFS写法 #include <map> #include <set> #include <list> #

Dancing Links [Kuangbin带你飞] 模版及题解

学习资料: http://www.cnblogs.com/grenet/p/3145800.html http://blog.csdn.net/mu399/article/details/7627862 2份模版 第一份精确覆盖 from POJ 3074 const int N = 9; const int MAXN = N * N * N + 10; const int MAXM = N * N * 4 + 10; const int MAXNODE = MAXN * 4 + MAXM +

「kuangbin带你飞」专题十八 后缀数组

layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kuangbin - 字符串 - 后缀数组 传送门 倍增法 struct DA{ bool cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } int t1[maxn],t2[maxn],c[maxn]; int r

kuangbin带你飞专题一 简单搜索 题解

目录 [kuangbin带你飞]专题一 简单搜索 [kuangbin带你飞]专题一 简单搜索 总结:用时2天半终于把这个专题刷完了 对于最基础的dfs bfs 路径打印 状态转移也有了一点自己些微的理解 其实2天半可以压缩到1天半的 主要是自己太懒了...慢慢加油刷bin神的专题呀 从大二下学期开始学算法 一开始就知道这个专题 一开始对于这个专题里的所有问题感觉都好难啊..就直接放弃了 看lrj的书 现在看到这个专题还挺唏嘘的吧 突然觉得思维和想法也不是很难 果然是那个时候心不静&还是储量不够吗

Tarjan 联通图 Kuangbin 带你飞 联通图题目及部分联通图题目

Tarjan算法就不说了 想学看这 https://www.byvoid.com/blog/scc-tarjan/ https://www.byvoid.com/blog/biconnect/ 下面是几份基本的模版 首先是无向图割点桥的代码 下面的代码是用于求割点数目的 其中add_block[u] = x  表示删除u点之后增加的联通块个数.注意是增加的联通块个数 const int MAXN = 1010; const int MAXM = 10010; const int INF = 0x

「kuangbin带你飞」专题十二 基础DP

layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 传送门 A.HDU1024 Max Sum Plus Plus 题意 给你N个数,然后你分成M个不重叠部分,并且这M个不重叠部分的和最大. 思路 动态规划最大m字段和,dp数组,dp[i][j]表示以a[j]结尾的,i个字段的最大和 两种情况:1.第a[j

「kuangbin带你飞」专题二十二 区间DP

layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - kuangbin - 区间DP - 动态规划 传送门 B.LightOJ - 1422 Halloween Costumes 题意 按顺序参加舞会,参加一个舞会要穿一种衣服,可以在参加完一个舞会后套上另一个衣服再去参加舞会,也可以在参加一个舞会的时候把外面的衣服脱了,脱到合适的衣服,但是脱掉的衣服不能再穿,参加完

「kuangbin带你飞」专题二十 斜率DP

layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 - 斜率DP 传送门 A.HDU - 3507 Print Article 题意 就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 题解 概率DP的入门题,把我搞得要死要活的. 首先dp[i]表示输出前i

[kuangbin带你飞]专题十六 KMP &amp; 扩展KMP &amp; Manacher :G - Power Strings POJ - 2406(kmp简单循环节)

[kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher G - Power Strings POJ - 2406 题目: Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of