gggyt  
没谁离不开谁

  后缀自动机

 

/** @xigua */
#include <stdio.h>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <cstring>
#include <queue>
#include <set>
#include <string>
#include <map>
#include <climits>
#define PI acos(-1)
#define rep(a,b,c) for(int (a)=(b); (a)<(c); ++(a))
#define drep(a,b,c) for(int (a)=(b); (a)>(c); --(a))
#define CLR(x) memset(x, 0, sizeof(x))
#define sf scanf
#define pf printf
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 250000  + 1000;
const int ma = 1e5 + 1000;
const int mod = 1e9 + 7;
const int INF = 1e8 + 5;
const ll inf = 1e17 + 5;
const db eps = 1e-6;
const int MAXN = 2e5+1e3;
struct SAM{
    int ch[maxn<<1][26];
    int fa[maxn<<1], len[maxn<<1];
    int cnt, last, root;
    void init() {
        root=1;
        memset(ch, 0, sizeof(ch));
        memset(fa, 0, sizeof(fa));
        last=cnt=root;
    }
    void add(int c) {
        int p=last, np=last=++cnt;
        len[np]=len[p]+1;
        while(!ch[p][c] && p) {
            ch[p][c]=np;
            p=fa[p];
        }
        if (p==0)  fa[np]=1;
        else {
            int q = ch[p][c];
            if(len[p] + 1 == len[q]) {
                fa[np] = q;
            }
            else {
                int nq = ++cnt;
                len[nq] = len[p] + 1;
                memcpy(ch[nq], ch[q], sizeof ch[q]);
                fa[nq] = fa[q];
                fa[q] = fa[np] = nq;
                while(ch[p][c] == q && p) {
                    ch[p][c] = nq;
                    p = fa[p];
                }
            }
        }
    }
    int find(char *s) {
        int p=root, l=0, c=0;
        int lenn=strlen(s);
        for(int i = 0; i < lenn; i++) {
            if(ch[p][s[i] - 'a']) {
                p = ch[p][s[i] - 'a'];
                c++;
            }
            else {
                while(p&&!ch[p][s[i]-'a'])  p=fa[p];
                if (!p)  c=0, p=1;
                else  c=len[p]+1, p=ch[p][s[i]-'a'];
            }
            l = max(l, c);
        }
        printf("%d\n", l);
    }
}sam;
char s[maxn];
void solve() {
    scanf("%s", s);
    int lenn=strlen(s);
    sam.init();
    for (int i=0; i<lenn; i++) {
        sam.add(s[i]-'a');
    }
    scanf("%s", s);
    sam.find(s);
}
int main() {
    int t = 1, cas = 1;
    //freopen("in.txt", "r", stdin);
   // freopen("out.txt", "w", stdout);
    //scanf("%d", &t);
    while(t--) {
       // printf("Case %d: ", cas++);
        solve();
    }
    return 0;
}

   回文树板子【已更改。再乱初始化我吃屎!】注意初始化!!:

 

/*  gyt
       Live up to every day            */
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<queue>
#include<set>
#include<string>
#include<map>
#include <time.h>
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 1e5+10;
const int sigma=26;
const ll mod = 1000000007;
const int INF = 0x3f3f3f;
const db eps = 1e-9;
struct ptree{
    char s[maxn];
    int next[maxn][sigma], fail[maxn], cnt[maxn], len[maxn];
    int last, n, p;
    ll res;
    inline int newnode(int l) {
        memset(next[p], 0, sizeof(next[p]));
        cnt[p]=0;
        len[p]=l;
        return p++;
    }
    inline void init() {
        n=0, p=0, last=0;
        newnode(0), newnode(-1);
        s[n]=-1;
        fail[0]=1;
    }
    inline int FL(int x) {
        while(s[n-len[x]-1]!=s[n])  x=fail[x];
        return x;
    }
    int add(char c) {
        c-='a';
        s[++n]=c;
        int cur=FL(last);
        if (!next[cur][c]) {
            int now=newnode(len[cur]+2);
            fail[now]=next[FL(fail[cur])][c];
            cnt[now]=cnt[fail[now]]+1;
            next[cur][c]=now;
        }
        last=next[cur][c];
        return cnt[last];
    }
}p;
char s[maxn];
ll sum[maxn];
void solve(){
    while(scanf("%s",s)!=EOF) {
        int len=strlen(s);
        p.init();
        memset(sum, 0, sizeof(sum));
        ll ans=0;
        for (int i=len-1; i>=0; i--) {
            sum[i] = sum[i+1]+p.add(s[i]);
        }
        p.init();
        for (int i=0; i<len; i++) {
            ans += (ll)p.add(s[i])*sum[i+1];
        }
        printf("%lld\n", ans);
    }
}
int main() {
    int t = 1;
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    //scanf("%d", &t);
    while(t--)
        solve();
    return 0;
}

   超强回文树板子:

const int MAXN = 100005, SIZE = 26;  
struct Palindromic_Tree {  
    int next[MAXN][SIZE];//next指针  
    int fail[MAXN];//fail指针  
    int cnt[MAXN];//表示节点i表示的回文串的个数(建树时求出的不是完全的,最后Count()函数跑一遍以后才是正确的)  
    int num[MAXN];//表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数  
    int len[MAXN];//len[i]表示节点i表示的回文串的长度(一个节点表示一个回文串)  
    int S[MAXN];//存放添加的字符  
    int last;//指向上一个字符所在的节点,方便下一次add  
    int n;//字符数组指针  
    int p;//节点指针  
    int NewNode(int L) {//新建节点  
        for(int i = 0; i < SIZE; ++i)  
            next[p][i] = 0;  
        cnt[p] = num[p] = 0;  
        len[p] = L;  
        return p++;  
    }  
    void Init() {//初始化  
        p = n = 0;  
        NewNode(0); NewNode(-1);  
        last = 0;  
        S[n] = -1;//开头放一个字符集中没有的字符,减少特判  
        fail[0] = 1;  
    }  
    int GetFail(int x) {//和KMP一样,失配后找一个尽量最长的  
        while(S[n - len[x] - 1] != S[n]) x = fail[x];  
        return x;  
    }  
    int Add(int c) {  
        S[++n] = c;  
        int cur = GetFail(last);//通过上一个回文串找这个回文串的匹配位置  
        if(!next[cur][c]) {//如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串  
            int now = NewNode(len[cur] + 2);//新建节点  
            fail[now] = next[GetFail(fail[cur])][c];//和AC自动机一样建立fail指针,以便失配后跳转  
            next[cur][c] = now;  
            num[now] = num[fail[now]] + 1;  
        }  
        last = next[cur][c];  
        cnt[last]++;  
        return num[last];  
    }  
    void Count() {  
        for(int i = p - 1; i >= 0; --i)  
            cnt[fail[i]] += cnt[i];  
        //父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!  
    }  
}tree;  

   凸包极角排序(得到最后形成凸包的点)Graham扫描算法:

#include<stdio.h>
#include<math.h>
#define eps 1e-10
#define pi 3.1415926535898
#define N 1010
/*
point[]:输入的点集
ch[]:输出的凸包上的点集,按照逆时针方向排列
n:point中的点的数目
len:输出的凸包上的点的个数
*/
struct node
{
    double x,y;
} point[N],ch[N];
int n,len;
double multi(node a,node b,node c)
{
    return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}
double dis(node a,node b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void graham_scan(node point[N],node ch[N],int n)
{
    int i,j,k,top;
    struct node t;
    k=0; //找到最下且偏左的那个点
    for(i=1; i<n; i++)
        if(point[i].y<point[k].y||(point[i].y==point[k].y&&(point[i].x<point[k].x)))
            k=i;
    t=point[0];//将这个点指定为point[0];
    point[0]=point[k];
    point[k]=t;
    //按极角从小到大,距离偏短进行排序
    for(i=1; i<n-1; i++)
    {
        k=i;
        for(j=i+1; j<n; j++)
            if(multi(point[j],point[k],point[0])>0||(fabs(multi(point[j],point[k],point[0]))<=eps&&
                    (dis(point[0],point[j])<dis(point[0],point[k]))))
                k=j; //k保存极角最小的那个点,或者相同距离原点最近
        t=point[i];
        point[i]=point[k];
        point[k]=t;
    }
    //第三个点先入栈
    ch[0]=point[0];
    ch[1]=point[1];
    ch[2]=point[2];
    top=2; //判断与其余所有点的关系
    for(i=3; i<n; i++)
    {
        //不满足向左转的关系,栈顶元素出栈
        while(multi(point[i],ch[top],ch[top-1])>0||fabs(multi(point[i],ch[top],ch[top-1]))<=eps)
            top--;
        //当前点与栈内所有点满足向左关系,因此入栈
        ch[++top]=point[i];
    }
    len=top+1;
}
int main()
{
    int i;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0; i<n; i++)
            scanf("%lf%lf",&point[i].x,&point[i].y);
        graham_scan(point,ch,n);
        for(i=0; i<len; i++)
            printf("%lf %lf\n",ch[i].x,ch[i].y);
    }
    return 0;
}

 

posted on 2017-09-14 22:00  gggyt  阅读(158)  评论(0编辑  收藏  举报