后缀数组 专题

国家队论文链接:

(更新中)

poj 1226 Substrings http://poj.org/problem?id=1226

/**************************************************************
    Problem:poj 1226
    User: youmi
    Language: C++
    Result: Accepted
    Time:0MS
    Memory:1056K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep0(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define rep_1(i,n) for(int i=n;i>=1;i--)
#define rep_0(i,n) for(int i=n-1;i>=0;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define esp 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl

using namespace std;
typedef long long ll;

const int maxn=200100;
int wa[maxn],wb[maxn],wv[maxn],cnt[maxn];
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++) cnt[i]=0;
     for(i=0;i<n;i++) cnt[x[i]=r[i]]++;
     for(i=1;i<m;i++) cnt[i]+=cnt[i-1];
     for(i=n-1;i>=0;i--) sa[--cnt[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++) cnt[i]=0;
       for(i=0;i<n;i++) cnt[wv[i]]++;
       for(i=1;i<m;i++) cnt[i]+=cnt[i-1];
       for(i=n-1;i>=0;i--) sa[--cnt[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++;
     }
     return;
}
int rk[maxn],height[maxn];
void calheight(int *r,int *sa,int n)
{
     int i,j,k=0;
     for(i=1;i<=n;i++) rk[sa[i]]=i;
     for(i=0;i<n;height[rk[i++]]=k)
     for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
     return;
}
char str[maxn];
int r[maxn],sa[maxn];
int who[maxn];
int vis[500];
int n,m;
bool check(int temp)
{
    int tot=0;
    zeros(vis);
    for(int i=2;i<=n;i++)
    {
        if(height[i]<temp)
        {
            tot=0;
            zeros(vis);
        }
        else
        {
            if(!vis[who[sa[i]]])
            {
                vis[who[sa[i]]]=1;
                tot++;
            }
            if(!vis[who[sa[i-1]]])
            {
                vis[who[sa[i-1]]]=1;
                tot++;
            }
            if(tot==m)
                return true;
        }
    }
    return false;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int T_T;
    scanf("%d",&T_T);
    for(int kase=1;kase<=T_T;kase++)
    {
        n=0;
        int sp=150;
        sc(m);
        rep1(i,m)
        {
            scs(str);
            int s1=strlen(str);
            for(int j=0;str[j];j++)
            {
                who[n]=i;
                r[n++]=str[j];
            }
            who[n]=sp;
            r[n++]=sp++;
            for(int j=0;str[j];j++)
            {
                who[n]=i;
                r[n++]=str[s1-j-1];
            }
            who[n]=sp;
            r[n++]=sp++;
        }
        r[n]=0;
        da(r,sa,n+1,sp);
        calheight(r,sa,n);
        int l=0,r=strlen(str);
        int mid=0,ans=0;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(check(mid))
            {
                l=mid+1;
                ans=mid;
            }
            else
                r=mid-1;
        }
        pt(ans);
    }
    return 0;
}
时间: 2024-10-19 18:08:30

后缀数组 专题的相关文章

后缀数组专题

后缀数组基本模板 ①倍增法(时间O(NlogN),空间O(N)) 1 #include<iostream> 2 using namespace std; 3 const int maxl = 100010; 4 char s[maxl]; 5 int totlen; 6 int r2[maxl], cc[maxl],SA[maxl], RANK[maxl], Height[maxl]; 7 //r2:以第二关键字对后缀排序所得的辅助数组 8 //cc:计数排序辅助数组 9 //RANK:RAN

Power Strings POJ - 2406(next水的一发 || 后缀数组)

后缀数组专题的 emm.. 就next 循环节../ 有后缀数组也可以做 从小到大枚举长度i,如果长度i的子串刚好是重复了len/i次,应该满足len % i == 0和rank[0] - rank[i] == 1(整个串的等级比 i位置开始的后缀的等级大1  (i位置开始的后缀即为比总串低一个等级的后缀)) 和height[rank[0]] == len-i (整个串 和 比它低一个等级的串的最长公共前缀的长度 是总长度减去这个循环节的长度)这些条件的 #include <iostream>

Spoj-DISUBSTR - Distinct Substrings~New Distinct Substrings SPOJ - SUBST1~(后缀数组求解子串个数)

Spoj-DISUBSTR - Distinct Substrings New Distinct Substrings SPOJ - SUBST1 我是根据kuangbin的后缀数组专题来的 这两题题意一样求解字符串中不同字串的个数: 这个属于后缀数组最基本的应用 给定一个字符串,求不相同的子串的个数. 算法分析: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数. 如果所有的后缀按照 suffix(sa[1]), suffix(sa[2]), suffix(sa

「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

【集训第五天&#183;后缀数组】哇哈哈哈哈~

前面放了几天假(虽然我们是在补课),所以懒得写博客.补课期间学习了网络流,后面写专题总结.网络流主要是建模,慢慢搞. 后缀数组这个东西非常难搞,当初老师讲的时候  我(lao)们(shi) 水了2h,讲完还是一脸懵逼.虽然思路是理解了,但是完全不知道代码是什么意思.cnm 然后某一天晚上我没交手机,坐在寝室的床上从23点啃代码啃到00:30,终于是明白了..cnm ------------------------------------------------------------------

SPOJ 705 Distinct Substrings(后缀数组)

[题目链接] http://www.spoj.com/problems/SUBST1/ [题目大意] 给出一个串,求出不相同的子串的个数. [题解] 对原串做一遍后缀数组,按照后缀的名次进行遍历, 每个后缀对答案的贡献为n-sa[i]+1-h[i], 因为排名相邻的后缀一定是公共前缀最长的, 那么就可以有效地通过LCP去除重复计算的子串. [代码] #include <cstdio> #include <cstring> #include <algorithm> usi

hdu5769--Substring(后缀数组)

题意:求含有某个字母的某个字符串的不同子串的个数 题解:后缀数组,记录每个位置距离需要出现的字母的距离就可以了.因为不太了解后缀模版卡了一会,还是很简单的. 记住sa和height数组都是1-n的下标. //后缀数组 #include <stdio.h> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll;

hdu 3518 Boring counting 后缀数组LCP

题目链接 题意:给定长度为n(n <= 1000)的只含小写字母的字符串,问字符串子串不重叠出现最少两次的不同子串个数; input: aaaa ababcabb aaaaaa # output 2 3 3 思路:套用后缀数组求解出sa数组和height数组,之后枚举后缀的公共前缀长度i,由于不能重叠,所以计数的是相邻height不满足LCP >= i的. 写写对后缀数组倍增算法的理解: 1.如果要sa数组对应的值也是1~n就需要在最后加上一个最小的且不出现的字符'#',里面y[]是利用sa数

【tyvj1860】后缀数组

描述 我们定义一个字符串的后缀suffix(i)表示从s[i]到s[length(s)]这段子串.后缀数组(Suffix array)SA[i]中存放着一个排列,满足suffix(sa[i])<suffix(sa[i+1]) 按照字典序方式比较定义height[i]表示suffix(sa[i])与suffix(sa[i-1])之间的最长公共前缀长度,其中height[1]=0你的任务就是求出SA和height这两个数组.字符串长度<=200000 输入格式 一行,为描述中的字符串(仅会出现小写