zoukankan      html  css  js  c++  java
  • 板子3

      后缀自动机

    /** @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
    ", 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
    ", 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
    ",ch[i].x,ch[i].y);
        }
        return 0;
    }
  • 相关阅读:
    js压缩图片上传插件localResizeIMG
    valueOf函数详解
    垂直居中
    word-wrap,word-break,white-space
    理解bind函数
    float失效的情况
    塞码考试系统里的输入,到底是怎么回事
    理解position:relative
    border实现三角形的原理
    函数是对象,函数名是指针
  • 原文地址:https://www.cnblogs.com/gggyt/p/7523317.html
Copyright © 2011-2022 走看看