Codeforces 235 C
题目大意
给定一个模板串, 再给出\(n\)个询问, 询问每一个串的循环串总共在原串中出现了多少次.
循环串: 比如说有\(str[] = \{ABCD\}\), 则其循环串有\(\{ABCD\}, \{BCDA\}, \{CDAB\}, \{DABC\}\), 共\(len\)个.
题解
把每一个串复制一遍放在原串后面: \(\{ABCD\} \to \{ABCDABC\}\), 放入原串的后缀自动机中匹配. 在匹配时, 假如下一位无法匹配, 则跳suffix link; 假如即使跳了suffix link, 最大长度\(len(suffix)\)仍然大于等于原串长度, 则也跳suffix link(相当于砍掉多余的部分).
放入SAM前要先跑一次KMP去循环节.
#include <cstdio>
#include <cstring>
#include <vector>
const int LEN = (int)1e6;
struct suffixAutomaton
{
    struct state
    {
        state *suc[26], *pre;
        int len;
        int sz, tg;
        std::vector<state*> bck;
        inline state()
        {
            for(int i = 0; i < 26; ++ i)
                suc[i] = NULL;
            pre = NULL;
            sz = 1;
            bck.clear();
            tg = 0;
        }
    };
    state *rt, *lst;
    inline void insert(int c)
    {
        state *u = new state;
        u->len = lst->len + 1;
        for(; lst != NULL && lst->suc[c] == NULL; lst->suc[c] = u, lst = lst->pre);
        if(lst == NULL)
            u->pre = rt;
        else
        {
            state *p = lst->suc[c];
            if(p->len == lst->len + 1)
                u->pre = p;
            else
            {
                state *q = new state;
                *q = *p;
                q->len = lst->len + 1, q->sz = 0;
                p->pre = u->pre = q;
                for(; lst != NULL && lst->suc[c] == p; lst->suc[c] = q, lst = lst->pre);
            }
        }
        lst = u;
    }
    void DFS(state *u)
    {
        u->tg = 1;
        if(u->pre != NULL)
            u->pre->bck.push_back(u);
        for(int i = 0; i < 26; ++ i)
            if(u->suc[i] != NULL && ! u->suc[i]->tg)
                DFS(u->suc[i]);
    }
    void get(state *u)
    {
        for(std::vector<state*>::iterator p = u->bck.begin(); p != u->bck.end(); ++ p)
            get(*p), u->sz += (*p)->sz;
    }
    inline void build(char *str, int len)
    {
        lst = rt = new state;
        rt->len = 0;
        for(int i = 0; i < len; ++ i)
            insert(str[i] - 'a');
        DFS(rt);
        get(rt);
    }
    inline int match(char *str, int len, int cir)
    {
        state *u = rt;
        int cur = 0;
        long long ans = 0;
        for(int i = 0; i < len + cir - 1; ++ i)
        {
            for(; u != rt && u->suc[str[i] - 'a'] == NULL; cur = u->pre->len, u = u->pre);
            if(u->suc[str[i] - 'a'] != NULL)
                u = u->suc[str[i] - 'a'], ++ cur;
            for(; u != rt && u->pre->len >= len; cur = u->pre->len, u = u->pre);
            if(cur >= len)
                ans += u->sz;
        }
        return ans;
    }
}SAM;
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("CF235C.in", "r", stdin);
    #endif
    static char str[LEN];
    scanf("%s", str);
    int len = strlen(str);
    SAM.build(str, len);
    int n;
    scanf("%d\n", &n);
    for(int i = 0; i < n; ++ i)
    {
        static char str[LEN << 1];
        scanf("%s", str);
        int len = strlen(str);
        static int nxt[LEN];
        nxt[0] = -1;
        int p = nxt[0];
        for(int i = 1; i < len; ++ i)
        {
            for(; ~ p && str[i] ^ str[p + 1]; p = nxt[p]);
            nxt[i] = str[i] == str[p + 1] ? ++ p : p;
        }
        int cir = len % (len - nxt[len - 1] - 1) == 0 ? len - nxt[len - 1] - 1 : len;
        for(int i = 0; i < cir; ++ i)
            str[i + len] = str[i];
        printf("%d\n", SAM.match(str, len, cir));
    }
}
Codeforces 235 C的更多相关文章
- [codeforces 235]A. LCM Challenge
		[codeforces 235]A. LCM Challenge 试题描述 Some days ago, I learned the concept of LCM (least common mult ... 
- codeforces 235 div2 C Team
		题目:http://codeforces.com/contest/401/problem/C 题意:n个0,m个1,求没有00或111的情况. 这么简单的题..... 做题的时候脑残了...,今天,贴 ... 
- codeforces 235 B. Let's Play Osu!
		You're playing a game called Osu! Here's a simplified version of it. There are n clicks in a game. F ... 
- codeforces 235 div2 B. Sereja and Contests
		Sereja is a coder and he likes to take part in Codesorfes rounds. However, Uzhland doesn't have good ... 
- codeforces 235 div2 A. Vanya and Cards
		Vanya loves playing. He even has a special set of cards to play with. Each card has a single integer ... 
- Codeforces 235 E Number Challenge
		Discription Let's denote d(n) as the number of divisors of a positive integer n. You are given three ... 
- codeforces 235 B lets play osu!
		cf235B 一道有意思的题.(据说是美少女(伪)计算机科学家出的,hh) 根据题目要求,就是求ni^2的和. 而n^2=n*(n-1)+n; n*(n-1)=C(n,2)*2: 所以∑ai^2=∑a ... 
- [ BZOJ 4318 & 3450 / CodeForces 235 B ] OSU!
		\(\\\) \(Description\) 一共进行\(N\)次操作,生成一个长度为\(N\)的\(01\)序列,成功对应\(1\),失败对应\(0\),已知每一次操作的成功率\(p_i\). 在这 ... 
- Codeforces Round #235 (Div. 2) D. Roman and Numbers 状压dp+数位dp
		题目链接: http://codeforces.com/problemset/problem/401/D D. Roman and Numbers time limit per test4 secon ... 
随机推荐
- 并查集:POJ1182-食物链(并查集比较高端的应用)
			食物链 Time Limit: 1000MS Memory Limit: 10000K Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C ... 
- git push后是空目录,且提示modified content, untracked content
			最近往自己的github传代码时,每一步都正常,但最后push上去之后是空目录,且在本地执行git status时提示: 后来发现是由于push的工程下本来就有个.git目录,所以才导致push上去的 ... 
- servlet 作用
			什么是Servlet Servlet是一个Java编写的程序,此程序是基于Http协议的,在服务器端运行的(如tomcat),是按照Servlet规范编写的一个Java类. 在BS架构中,早期的Web ... 
- 你应该知道的.net平台下socket异步通讯(代码实例)
			1,首先添加两个windows窗体项目,一个作为服务端server,一个作为客户端Client 2,然后添加服务端代码,添加命名空间,界面上添加TextBox控件 using System.Net; ... 
- tomcat6-endpoint设计
			之前写的一个ppt 搬到博客来 
- python - work5 - 类与对象 - 拓展题
			''' 5:购物车类,包含的功能如下,请自行设计这个类以及类里面的方法:1)用户输入工资后,打印商品列表(商品列表自行设计展示模式)2)允许用户根据商品编号去选择商品3)用户选择商品后,检查余额是否足 ... 
- 从几率到logisitic函数
			odds 几率,又称事件的优势比.几率和概率的关系如下: o=p1−pp=o1+o Logistic 回归模型的因变量只有 1/0 两种取值.假设在 p 个独立自变量 x1,x2,…,xp 作用下,记 ... 
- equals()和hashCode()方法在集合类set中的使用
			Object的方法 equals()和hashCode() 是用来判断两个对象是否相等.基础类型判断是否相等时,使用“==”来判断,按java的说话,“==”当用来判断是基础类型是判断内容的,而引用对 ... 
- 【bzoj3251】树上三角形  朴素LCA+暴力
			题目描述 给定一大小为n的有点权树,每次询问一对点(u,v),问是否能在u到v的简单路径上取三个点权,以这三个权值为边长构成一个三角形.同时还支持单点修改. 输入 第一行两个整数n.q表示树的点数和操 ... 
- 搜索引擎快捷导航:一个简单的chrome插件(教程)
			一.如何通过练习来提高学习新框架的最好姿势是:基于现有的业务来学习.即从工作中学习,从实践中学.但是,如果一直只使用新的框架来重写旧的业务,成长也会趋近于0.第一次,使用新框架时收获可能颇丰:第二次, ... 
