zoukankan      html  css  js  c++  java
  • Jomoo的模板

    by Jomoo

    1 杂类算法

    1.1 快读模板

    template <typename Int>
    inline Int read()       
    {
        Int flag = 1;
        char c = getchar();
        while ((!isdigit(c)) && c != '-') c = getchar();
        if (c == '-') flag = -1, c = getchar();
        Int init = c & 15;
        while (isdigit(c = getchar())) init = (init << 3) + (init << 1) + (c & 15);
    	return init * flag;
    }
    
    template <typename Int>
    inline Int read(char &c)       
    {
        Int flag = 1;
        c = getchar();
        while ((!isdigit(c)) && c != '-') c = getchar();
        if (c == '-') flag = -1, c = getchar();
        Int init = c & 15;
        while (isdigit(c = getchar())) init = (init << 3) + (init << 1) + (c & 15);
    	return init * flag;
    }
    
    template <typename Int>
    inline void write(Int x)
    {
        if (x < 0) putchar('-'), x = ~x + 1;
        if (x > 9) write(x / 10);
        putchar((x % 10) | 48);
    }  
    
    template <typename Int>
    inline void write(Int x, char nextch)
    {
        write(x);
        putchar(nextch);
    }
    
    int main()
    {
        return 0;
    }
    

    1.2 O(1) int64 乘法

    LL mul(LL a, LL b, LL P){
        LL L = a * (b >> 25LL) % P * (1LL << 25) % P;
        LL R = a * (b & ((1LL << 25) - 1)) % P;
        return (L + R) % P;
    }
    

    2 图论算法

    2.1 树类 - Trie

    #define TrieNodeMax 100007 
    // should @using namespace std
    template <int charSetSize = 26, char base = 'a'>
    struct Trie {
        bool isEndStr[TrieNodeMax];
        int son[TrieNodeMax][charSetSize], top = 1;
        bool insert(string s)
        {
            int u = 1;
            for (int i = 0; i < s.length(); i++) {
                if (!son[u][s[i] - base]) {
                    son[u][s[i] - base] = ++top;
                } else if (isEndStr[son[u][s[i] - base]] || i == s.length() - 1) return 0;
                u = son[u][s[i] - base];
                if (i == s.length() - 1) isEndStr[u] = 1;
            }
            return 1;
        }
    };
    

    2.2 树类 - 并查集(NB version)

    复杂度 (O(nalpha{(n)})),不用辅助数组

    struct UFS {
        int fa[400007];
        int familyCnt;
    
        UFS() : familyCnt(0)
        {
            memset(fa, -1, sizeof(fa));
        }
    
        int find(int u)
        {
            return fa[u] < 0 ? u : fa[u] = find(fa[u]);
        }
    
        void connect(int x, int y)
        {
            int xx = find(x), yy = find(y);
            if (xx == yy) return;
            if (fa[xx] > fa[yy]) swap(xx, yy);
            fa[xx] += fa[yy];
            fa[yy] = xx;
            familyCnt--;
        }
    
        bool isFamily(int u, int v)
        {
            return find(u) == find(v);
        }
    } fam;
    

    2.3 树类 - LCA

    void dfs_LCA(int now, int depth) 
    {
        use[now] = true;
        deep[now] = depth;
        for (rg int k = 1; k <= SizeLogN; k++){
            f[now][k] = f[f[now][k - 1]][k - 1];
        }
        for (rg EDGE *nxt = v[now]; nxt; nxt = nxt->next_edge) {
            if(!use[nxt->e]) {
                f[nxt->e][0] = now;
                dfs_LCA(nxt->e, depth + 1);
            }
        }
    // 	use[now] = false;
    } 
    
    inline int jump(int u, int depth) {
        for (rg int k = 0; k <= SizeLogN; k++) {
            if ((depth & (1 << k))) u = f[u][k];
        }
        return u;
    }
    
    inline int LCA(int u, int v){
        if (deep[u] < deep[v]) swap(u, v);
        u = jump(u, deep[u] - deep[v]);
        for (rg int k = SizeLogN; k >= 0; k--) {
            if (f[u][k] != f[v][k]) u = f[u][k], v = f[v][k]; 
        }
        return u == v ? u : f[u][0];
    }
    	
    f[s][0] = 0;
    dfs_LCA(s, 0);
    LCA(u, v);
    

    2.4 树类 - 超级树状数组

    [sum[i]=sum_{j=1}^ia[j]+sum_{j=1}^idelta[j]*(i-j+1) ]

    [sum[i]=sum_{j=1}^ia[j]+(i+1)*sum_{j=1}^idelta[j]-sum_{j=1}^idelta[j]*j ]

    (basicSum) 数组维护 (a) 数组的前缀和
    (delta1)(delta2) 两个树状数组,(delta1) 维护 (delta) 数组的和,(delta2) 维护(delta[i]*i) 的和

    template <typename Int>
    class super_BIT {
      private:
      	Int n;
      	Int *basicSum, *delta1, *delta2;
      	
    	Int lowbit(Int x) 
    	{
    	    return x & (-x);
    	}
    	
    	void arr_add(Int *arr, Int pos, Int x) 
    	{
    	    while (pos <= n) {
    	    	arr[pos] += x;
    			pos += lowbit(pos);
    		}
    	}
    	
    	Int arr_getsum(Int *arr, Int pos)
    	{
    	    Int sum = 0;
    	    while (pos) {
    			sum += arr[pos];
    			pos -= lowbit(pos);
    		}
    	    return sum;
    	}
    	
    	void free_space()
    	{
    		delete[] basicSum;
    		delete[] delta1;
    		delete[] delta2;
    	}
      public:
      	super_BIT() 
    	{
      		basicSum = NULL;
      		delta1 = NULL;
      		delta2 = NULL;
    	}
      	~super_BIT() 
    	{
    		free_space(); 
    	}
      	
      	void init(Int size, Int *arr = NULL)
      	{
      		free_space();
      		n = size;
      		basicSum = new Int[size + 1];
      		delta1 = new Int[size + 1];
      		delta2 = new Int[size + 1];
      		memset(basicSum, 0, (size + 1) * sizeof(Int));
      		memset(delta1, 0, (size + 1) * sizeof(Int));
      		memset(delta2, 0, (size + 1) * sizeof(Int));
            if (arr != NULL) {
                for (Int i = 1; i <= n; i++) {
                    basicSum[i] = basicSum[i - 1] + arr[i];
                }
            }
    	}
    	
    	void modify(Int l, Int r, Int x)
    	{
    	    arr_add(delta1, l, x);
    		arr_add(delta1, r + 1, -x);
    		arr_add(delta2, l, x * l);
    		arr_add(delta2, r + 1, -x * (r + 1));
    	}
    	
    	Int getsum(Int r)
    	{
    		return basicSum[r] + arr_getsum(delta1, r) * (r + 1) - arr_getsum(delta2, r);
    	}
    	
    	Int query(Int l, Int r)
    	{
    	    return getsum(r) - getsum(l - 1);
    	}
    	
    	void sample(string problem)
    	{
    		if (problem == "LOJ - #132") {
    			Int N, Q;
    			Int *a = new Int[1000001];
    			N = read<Int>();
    			Q = read<Int>();
    			for (Int i = 1; i <= N; i++) {
    				a[i] = read<Int>();
    			}
    			init(N, a);
    			Int type, l, r, x;
    			while (Q--) {
    				type = read<Int>();
    				if (type == 1) {
    					l = read<Int>();
    					r = read<Int>();
    					x = read<Int>();
    					modify(l, r, x);
    				} else {
    					l = read<Int>();
    					r = read<Int>();
    					write(query(l, r), 10);
    				}
    				debug();
    			}
    		} else {
    			// do
    		}
    	}
    }; 
    

    2.5 树类 - 平衡树(STL)

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        vector<int> nums;
        int q;
        scanf("%d", &q);
        while (q--) {
            int t, x;
            scanf("%d %d", &t, &x);
            if (t == 1) {
                nums.insert(upper_bound(nums.begin(), nums.end(), x), x);
            } else if (t == 2) {
                nums.erase(lower_bound(nums.begin(), nums.end(), x));
            } else if (t == 3) {
                printf("%d
    ", lower_bound(nums.begin(), nums.end(), x) - nums.begin() + 1);
            } else if (t == 4) {
                printf("%d
    ", nums[x - 1]);
            } else if (t == 5) {
                printf("%d
    ", *--lower_bound(nums.begin(), nums.end(), x));
            } else {
                printf("%d
    ", *upper_bound(nums.begin(), nums.end(), x));
            }
        }
        return 0;
    }
    

    2.6 树类 AC-Trie

    2.6.1 模板 1

    给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。

    n行模式串
    1行文本串

    struct ACtrie {
        ACtrie *fail, *son[charSize];
        int count;
        bool found;
        int fa_sonId; // 在爸爸那里自己的ID,即本节点代表的字母
        ACtrie() : fail(NULL), count(0), found(0), fa_sonId('~' - baseChar)
        {
            memset(son, 0, sizeof(son));
        }
    };
    
    ACtrie *root = new ACtrie;
    
    void insert(string s)
    {
        ACtrie *p = root;
        for (string::iterator it = s.begin(); it != s.end(); it++) {
            if (!p->son[*it - baseChar]) {
                p->son[*it - baseChar] = new ACtrie;
                p->son[*it - baseChar]->fa_sonId = *it - baseChar;
            }
            p = p->son[*it - baseChar];
        }
        p->count++;
    }
    
    void make_fail()
    {
        queue<ACtrie*> q;
        for (int i = 0; i < charSize; i++) {
            if (root->son[i]) {
                // printf("CNT 63 - %c.
    ", i + baseChar);
                q.push(root->son[i]);
                root->son[i]->fail = root;
            }
        }
        while (!q.empty()) {
            ACtrie *p = q.front();
            q.pop();
            for (int i = 0; i < charSize; i++) {
                if (!p->son[i]) continue;
                ACtrie *f = p->fail;
                while (true) {
                    if (f->son[i]) {
                        p->son[i]->fail = f->son[i];
                        break;
                    }
                    if (f == root) {
                        p->son[i]->fail = root;
                        break;
                    }
                    f = f->fail;
                }
                q.push(p->son[i]);
            }
        }
    }
    
    void build_ACtrie(vector<string> sArr)
    {
        for (vector<string>::iterator it = sArr.begin(); it != sArr.end(); it++) {
            insert(*it);
        }
        make_fail();
    }
    
    int match_task1(string txt) // 有多少个模式串在文本串里出现过(多次出现答案只算1,重复的模式串答案算多个)
    {
        ACtrie *u = root, *v;
        int ans(0);
        for (string::iterator it = txt.begin(); it != txt.end(); it++) {
            if (u->son[*it - baseChar]) u = u->son[*it - baseChar];
            else {
                while (!u->son[*it - baseChar] && u != root) {
                    u = u->fail;
                }
                if (u->son[*it - baseChar]) {
                    u = u->son[*it - baseChar];
                }
            }
            
            v = u;
            while (v->count && !v->found) {
                ans += v->count;
                v->found = true;
                v = v->fail;
            }
        }
        return ans;
    }
    
    int main()
    {
        int n = read<int>();
        string s, txt;
        vector<string> v;
        for (int i = 1; i <= n; i++) {
            cin >> s;
            v.push_back(s);
        }
        build_ACtrie(v);
        cin >> txt;
        write(match_task1(txt), 10);
        return 0;
    }
    

    2.6.2 模板 2

    有 N 个由小写字母组成的模式串以及一个文本 T 。每个模式串可能会在文本串中出现多次。你需要找出(b)哪些(/b)模式串在文本串 T 中出现的次数最多。

    n行模式串
    1行文本串

    int TJ[150 + 7];
    const int charSize = 26;
    const char baseChar = 'a';
    
    struct ACtrie {
        ACtrie *fail, *son[charSize];
        int count;
        string originalString;
        bool found;
        int inputId;
        int fa_sonId; // 在爸爸那里自己的ID,即本节点代表的字母
        ACtrie() : fail(NULL), count(0), found(0), fa_sonId('~' - baseChar)
        {
            memset(son, 0, sizeof(son));
        }
    };
    
    ACtrie *root = new ACtrie;
    
    void insert(string s, int inputId)
    {
        ACtrie *p = root;
        for (string::iterator it = s.begin(); it != s.end(); it++) {
            if (!p->son[*it - baseChar]) {
                p->son[*it - baseChar] = new ACtrie;
                p->son[*it - baseChar]->fa_sonId = *it - baseChar;
            }
            p = p->son[*it - baseChar];
        }
        p->count++;
        p->originalString = s;
        p->inputId = inputId;
    }
    
    void make_fail()
    {
        queue<ACtrie*> q;
        for (int i = 0; i < charSize; i++) {
            if (root->son[i]) {
                q.push(root->son[i]);
                root->son[i]->fail = root;
            }
        }
        while (!q.empty()) {
            ACtrie *p = q.front();
            q.pop();
            for (int i = 0; i < charSize; i++) {
                if (!p->son[i]) continue;
                ACtrie *f = p->fail;
                while (true) {
                    if (f->son[i]) {
                        p->son[i]->fail = f->son[i];
                        // printf("char %c:find my pFail!
    ", i + baseChar);
                        break;
                    }
                    if (f == root) {
                        p->son[i]->fail = root;
                        break;
                    }
                    f = f->fail;
                }
                q.push(p->son[i]);
            }
        }
    }
    
    void build_ACtrie(vector<string> sArr)
    {
        int count = 0;
        for (vector<string>::iterator it = sArr.begin(); it != sArr.end(); it++) {
            insert(*it, count++);
        }
        make_fail();
    }
    
    void match(string txt) 
    {
        ACtrie *u = root, *v;
        for (string::iterator it = txt.begin(); it != txt.end(); it++) {
            if (u->son[*it - baseChar]) u = u->son[*it - baseChar];
            else {
                while (!u->son[*it - baseChar] && u != root) {
                    u = u->fail;
                }
                if (u->son[*it - baseChar]) {
                    u = u->son[*it - baseChar];
                }
            }
            
            v = u;
            while (v != root) {
                if (v->count) TJ[v->inputId]++;
                v = v->fail;
            }
        }
    }
    
    void clean(ACtrie *rt = root) 
    {
        rt->originalString = "";
        rt->count = 0;
        rt->inputId = 0;
        rt->fail = NULL;
        for (int i = 0; i < charSize; i++) {
            if (rt->son[i]) {
                clean(rt->son[i]);
                // delete rt->son[i];
            }
        }
    }
    
    struct forSort {
        string s;
        int id;
        int val;
        bool operator < (const forSort &other) const {
            return val ^ other.val ? val > other.val : id < other.id;;
        }
    } a[150 + 7];
    
    int main()
    {
        int n = read<int>();
        if (!n) return 0;
      sPosTAG:
        memset(Jalg::TJ, 0, sizeof(Jalg::TJ));
        Jalg::clean();
        string s, txt;
        vector<string> v;
        for (int i = 1; i <= n; i++) {
            cin >> s;
            v.push_back(s);
        }
        Jalg::build_ACtrie(v);
        cin >> txt;
        Jalg::match(txt);
        for (int i = 0; i < n; i++) {
            a[i] = (forSort){v[i], i, Jalg::TJ[i]};
        }
        sort(a, a + n);
        int ans = a[0].val;
        write(ans, 10); 
        int i = 0;
        while (i < n && a[i].val == ans) {
            printf("%s
    ", a[i++].s.c_str());
        }
        n = read<int>();
        if (n) goto sPosTAG;
        return 0;
    }
    

    2.7 图类 - 迪杰斯特拉

    struct Graph {
        struct Node {
            int u, val;
            bool operator < (const Node &other) const
            {
                return val > other.val;
            }
        };
        struct Edge {
            int v, w;
        } e[200007];
        int head[100007], next[200007], edgeCnt;
    
        Graph() : edgeCnt(0)
        {
            memset(head, -1, sizeof(head));
        }
    
        void addEdge(int u, int v, int w)
        {
            e[++edgeCnt] = (Edge){v, w};
            next[edgeCnt] = head[u];
            head[u] = edgeCnt;
        }
    
        void dij(int n, int s, int *dis)
        {
            memset(dis, 0x3f, sizeof(int) * (n + 1));
            dis[s] = 0;
            priority_queue<Node> q;
            q.push((Node){s, 0});
            while (!q.empty()) {
                while (q.top().val != dis[q.top().u] && !q.empty()) q.pop();
                if (q.empty()) break;
                int fr = q.top().u;
                q.pop();
                #define to e[i].v
                #define va e[i].w
                for (int i = head[fr]; ~i; i = next[i]) {
                    if (dis[to] - va > dis[fr]) {
                        dis[to] = dis[fr] + va;
                        q.push((Node){to, dis[to]});
                    }
                }
                #undef to
                #undef va
            }
        }
    } G;
    
    int main()
    {
        int n, m, s;
        int u, v, w;
        n = read<int>();
        m = read<int>();
        s = read<int>();
        while (m--) {
            u = read<int>();
            v = read<int>();
            w = read<int>();
            G.addEdge(u, v, w);
        }
        int *dis = new int[n + 1];
        G.dij(n, s, dis);
        for (int i = 1; i <= n; i++) {
            write
            (dis[i], 32);
        }
        return 0;
    }
    

    2.8 图类 - SPFA(带卡界)判负环

    struct Edge {
        int v, w;
        int nxt;
        Edge() {}
        Edge(int _v, int _w, int _nxt) : v(_v), w(_w), nxt(_nxt) {}
    } edges[6007]; 
    // 链式前向星存图
    int top = 1;
    int n, m;
    
    int head[2007] = {0};
    int dis[2007] = {0};
    bool inqueue[2007] = {0};
    
    inline void add_edge(int u, int v, int w) // 单次加边操作
    {
        edges[top] = Edge(v, w, head[u]);
        head[u] = top++;
    }
    
    inline void add(int u, int v, int w) // 加边操作
    {
        add_edge(u, v, w);
        if (w >= 0) add_edge(v, u, w);
    }
    
    const double K = 20.076030; // 即题解中所说的 "T"
    bool SPFA_bfs()
    { 
        queue <int> q;
        q.push(1);
        inqueue[1] = 1;
        int times = 0; 
        while (!q.empty()) {
            times++;
            if (times > K * (n + m)) return 1;
            // 以上两行:卡界
            int n = q.front(); q.pop();
            inqueue[n] = 0;
            for (int i = head[n]; i != -1; i = edges[i].nxt) {
                Edge &e = edges[i];
                if (dis[e.v] > dis[n] + e.w) {
                    dis[e.v] = dis[n] + e.w;
                    if (!inqueue[e.v]) q.push(e.v);
                }
            }
        }
        return 0;
    }
    
    void van()
    {
        n = readint();
        m = readint();
        top = 1;
        memset(head, -1, sizeof(head));
        memset(dis, 0x3f, sizeof(dis));
        memset(inqueue, 0, sizeof(inqueue));
        dis[1] = 0;
        register int ui, vi, wi;
        for (register int i = 1; i <= m; i++) {
            ui = readint();
            vi = readint();
            wi = readint();
            add(ui, vi, wi);
        }
        if (SPFA_bfs()) puts("YE5");
        else puts("N0");
    }
    
    int main()
    {
        register int T = readint();
        while (T--) van();
        return 0;
    }
    

    2.9 图类 - 网络流

    P2045 方格取数加强版

    struct Edge {
        int u, v, w;
        int cost;
        int next;
        Edge() {}
        Edge(int _u, int _v, int _w, int _cost, int _next) : u(_u), v(_v), w(_w), cost(_cost), next(_next) {}
    };
    
    int n, k, s, t;
    Edge edges[300007]; 
    int head[5007], top = 0;
    int could[5007];
    int road[5007];
    int pre[5007];
    
    template <typename _Tp>
    void queue_clear(queue<_Tp> &a)
    {
        queue<_Tp> empty;
        swap(a, empty);
    }
    queue <int> q;
    
    void _add_once(int u, int v, int w, int cost)
    {
        edges[top] = Edge(u, v, w, cost, head[u]);
        head[u] = top++;
    }
    
    void add(int u, int v, int w, int cost)
    {
        _add_once(u, v, w, cost);
        _add_once(v, u, 0, -cost);
    }
    
    // 如果你想查看一些 DEBUG ,请去掉下一行开头的注释符号
    // #define TEST_OPEN
    // 【警告:仅限小数据(如小样例)】 
    
    #ifndef TEST_OPEN 
    #define fprintf(...)  
    #endif
    
    int dis[10007];
    bool SPFA()
    {
    	queue_clear(q);
        bool vis[10007] = {0};
        memset(dis, 0x3f, sizeof(dis));
        memset(could, 0x3f, sizeof(could));
        dis[s] = 0;
        vis[s] = 1;
        q.push(s);
        while (!q.empty()) {
            int now = q.front();
            q.pop();
            vis[now] = 0;
            for (int nNow = head[now]; nNow != -1; nNow = edges[nNow].next) {
                Edge &e = edges[nNow];
                if (e.w > 0 && dis[e.v] > dis[now] + e.cost) {
                    dis[e.v] = dis[now] + e.cost;
                    road[e.v] = nNow;
                    could[e.v] = min(could[now], e.w);
                    pre[e.v] = now;
                    if (!vis[e.v]) {
                        q.push(e.v);
                        vis[e.v] = 1;
                    }
                }
            }
        }
        if (dis[t] != 0x3f3f3f3f) return true; // success
        else return false; // unsuccess
    }
    
    void EK_MCMF() 
    {
        // EK_MCMF : 基于 EK 的 MCMF 算法 
    	//           (Edmonds Karp's "Min Cost Max Flow" algorithm)
        int maxflow = 0, mincost = 0;
    #ifdef TEST_OPEN
        int count = 0;
    #endif
        while (SPFA()) {
            for (int pNow = t; pNow != s; pNow = pre[pNow]) {
                edges[road[pNow]].w -= could[t];
                edges[road[pNow] ^ 1].w += could[t];
            }
            maxflow += could[t];
            mincost += dis[t] * could[t];
        }
        printf("%d", -mincost);
    #ifdef TEST_OPEN
        printf("
    DUBUG:maxflow = %d.
    ", maxflow);
    #endif
    }
    
    enum IN_OUT {
        IN = 0, 
        OUT = 1
    };
    
    int getrank(int x, int y, IN_OUT status)
    {
        return status * n * n + (x - 1) * n + y;
    }
    
    int main()
    {
        memset(head, -1, sizeof(head));
        scanf("%d%d", &n, &k);
        s = 0;
        t = getrank(n, n, OUT) + 1;
        add(s, getrank(1, 1, IN), k, 0);
        add(getrank(n, n, OUT), t, k, 0);
        int aij;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                scanf("%d", &aij);
                add(getrank(i, j, IN), getrank(i, j, OUT), 1, -aij);
                add(getrank(i, j, IN), getrank(i, j, OUT), k - 1, 0);
            }
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j < n; j++) {
                add(getrank(i, j, OUT), getrank(i, j + 1, IN), k, 0);
            }
        }
        for (int i = 1; i < n; i++) {
            for (int j = 1; j <= n; j++) {
                add(getrank(i, j, OUT), getrank(i + 1, j, IN), k, 0);
            }
        }
        EK_MCMF();
        return 0;
    }
    

    3 字符串算法

    3.1 KMP

    int nxt[1000007];
    int n, m;
    char a[1000007], b[1000007]; 
    
    void GetNext()
    {
        int j = 0, k = -1;
        nxt[0] = -1;
        while (j < m) {
            if (k == -1 || b[j] == b[k]) nxt[++j] = ++k;
            else k = nxt[k];
        }
    }
    
    void Match()
    {
        int j = -1, k = -1;
        while (j < n) {
            // printf("j %d k %d.
    ", j, k);
            if (k == -1 || a[j] == b[k]) j++, k++;
            else k = nxt[k];
            if (k == m) write(j - m + 1, 10), k = nxt[k];
        }
    }
    
    int main()
    {
        scanf("%s%s", a, b);
        n = strlen(a);
        m = strlen(b);
        GetNext();
        // for (int i = 0; i < m; i++) nxt[i]++;
        Match();
        // for (int i = 0; i < m; i++) write(nxt[i] + 1, 32);
        for (int i = 1; i <= m; i++) write(nxt[i], 32);
        return 0;
    }
    

    3.2 manacher

    char str[22000007] = {'|', '^'};
    int ans[22000007] = {0};
    
    int main() 
    {
        char ch;
        int len = 2;
        while ((ch = getchar()) != EOF) {
            str[len] = ch;
            len++;
            str[len] = '^';
            len++;
        }
        
        int mi_2(0), right(0);
        int maxLen = 0;
        for (int i = 1; i < len; i++) {
            ans[i] = right > i ? min(ans[mi_2 - i], right - i) : 1;
            
            while (str[i + ans[i]] == str[i - ans[i]])
                ans[i]++;
        
            if (right < i + ans[i]) {
                right = i + ans[i];
                mi_2 = i << 1;
            }
    
            if (maxLen < ans[i])
                maxLen = ans[i];
        }
        write(maxLen - 1);
        return 0; 
    }
    

    4 数论算法

    4.1 FFT

    version = fast,经典,不是我写的

    #define Maxn 1350000
    using namespace std;
    const double Pi=acos(-1);
    int n,m;
    struct CP
    {
      CP (double xx=0,double yy=0){x=xx,y=yy;}
      double x,y;
      CP operator + (CP const &B) const
      {return CP(x+B.x,y+B.y);}
      CP operator - (CP const &B) const
      {return CP(x-B.x,y-B.y);}
      CP operator * (CP const &B) const
      {return CP(x*B.x-y*B.y,x*B.y+y*B.x);}
    }f[Maxn<<1],p[Maxn<<1];
    int tr[Maxn<<1];
    void fft(CP *f,bool flag)
    {
      for (int i=0;i<n;i++)
        if (i<tr[i])swap(f[i],f[tr[i]]);
      //枚举区间长度 
      for(int p=2;p<=n;p<<=1){
        int len=p>>1;//待合并的长度
        CP tG(cos(2*Pi/p),sin(2*Pi/p));
        if(!flag)tG.y*=-1;//p次单位根
        for(int k=0;k<n;k+=p){//枚举起始点 
          CP buf(1,0);//遍历一个子问题并合并
          for(int l=k;l<k+len;l++){
            CP tt=buf*f[len+l];
            f[len+l]=f[l]-tt;
            f[l]=f[l]+tt;
            buf=buf*tG;
          }
        }
      }
    }
    int main()
    {
      scanf("%d%d",&n,&m);
      for (int i=0;i<=n;i++)scanf("%lf",&f[i].x);
      for (int i=0;i<=m;i++)scanf("%lf",&p[i].x);
      for(m+=n,n=1;n<=m;n<<=1);
      for(int i=0;i<n;i++)
        tr[i]=(tr[i>>1]>>1)|((i&1)?n>>1:0);
      fft(f,1);fft(p,1);//DFT
      for(int i=0;i<n;++i)f[i]=f[i]*p[i];
      fft(f,0);
      for(int i=0;i<=m;++i)printf("%d ",(int)(f[i].x/n+0.49));
      return 0;
    }
    

    version=slow,基础,我写的

    struct complex {
    	double x, y;
    	complex(double xx = 0, double yy = 0) : x(xx), y(yy) {}
    	
    	complex operator + (complex b)
    	{
    		return complex(x + b.x, y + b.y);
    	}
    	
    	complex operator - (complex b)
    	{
    		return complex(x - b.x, y - b.y);
    	}
    	
    	complex operator * (complex b)
    	{
    		return complex(x * b.x - y * b.y, x *b.y + y * b.x);
    	}
    } b[Maxn], c[Maxn];
    // struct_complex and operations
    int n, m, r[Maxn];
    
    void fft(complex *f, int op)
    {
    	for (int i = 0; i < n; i++) {
    		if (i < r[i]) {
    			complex tmp = f[i];
    			f[i] = f[r[i]];
    			f[r[i]] = tmp;
    		}
    	}
    	for (int p = 2; p <= n; p <<= 1) { 
    	    // $ O(log_n) $
    		int len = p / 2;
    		complex tmp(cos(Pi / len), op * sin(Pi / len));
    		for (register int k = 0; k < n; k += p) { 
    		    // $ O(log_n) $
    			register complex buf(1, 0);
    			for (register int l = k; l < k + len; l++) { 
    			    // $ O(log_n) $
    				register complex tt = buf * f[len + l];
    				f[len + l] = f[l] - tt;
    				f[l] = f[l] + tt;
    				buf = buf * tmp;
    			}
    		}
    	}
    }
    
    int main()
    {
    	n = read<int>();
    	m = read<int>();
    	for (register int i = 0; i <= n; i++) {
    		b[i].x = read<int>();
    	}
    	for (register int i = 0; i <= m; i++) {
    		c[i].x = read<int>();
    	}
    	m += n; 
    	n = 1;
    	while (n <= m) {
    		n <<= 1;
    	}
    	for (int i = 0; i < n; i++) {
    		r[i] = (r[i >> 1] >> 1) | ((i & 1) ? n >> 1 : 0);
    	}
    	fft(b, 1);
    	fft(c, 1);
    	// DFT
    	for (register int i = 0; i < n; i++) b[i] = b[i] * c[i];
    	fft(b, -1);
    	// IDFT
    	for (register int i = 0; i <= m; i++) {
    		printf("%.0f ", fabs(b[i].x) / n);
    	}
    	return 0;
    }
    
  • 相关阅读:
    使用阿里云ECS安装HDFS的小问题
    退役回忆录嘤嘤嘤
    2018 ICPC北京 H ac自动机
    Educational Codeforces Round 54 (Rated for Div. 2) DE
    sa learning
    网络流learning
    Python模块logging
    Python模块unittest
    Linux /dev/shm
    Shell 字符串操作
  • 原文地址:https://www.cnblogs.com/hkxadpall/p/OI-template.html
Copyright © 2011-2022 走看看