UVa 10679 - I Love Strings!!

题目:给你一个目标串,和一些模式串,问每个模式串是否在目标串中出现。

分析:字符串,AC自动机。一开始用KMP算法,TLE了才发现会超时,改用AC自动机;

直接利用AC自动机存储,查询即可,然后按顺序输出;

如果模式串中有重复的,直接利用并查集合并即可,只须判断父节点。

说明:╮(╯▽╰)╭计算复杂度时,数据组数被忽略了;注意初始化。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

char s[100002],t[1002];

#define nodesize 40004        //节点个数
#define dictsize 52           //字符集大小 

typedef struct node1
{
    int    flag;              //值域
    node1* fail;
    node1* next[dictsize];
}tnode;
tnode  dict[nodesize+1];
tnode* Q[nodesize+1];
int    ID[256];
int    visit[1002];
int    father[1002];

class AC_DFA
{
    private:
        int    size;
        tnode* root;
    public:
        AC_DFA() {makeID();init();}
        void makeID() {
            for ( int i = 0 ; i < 26 ; ++ i ) {
                ID['a'+i] = i;
            	ID['A'+i] = i+26;
			}
        }
        void init() {
            memset( dict, 0, sizeof( dict ) );
            root=NULL; size=0; root=newnode();
            for ( int i = 0 ; i < 1001 ; ++ i )
            	father[i] = i;
        }
        tnode* newnode() {
            dict[size].fail = root;
            return &dict[size ++];
        }
        void insert( char* word, int id ) {
            tnode* now = root;
            for ( int i = 0 ; word[i] ; ++ i ) {
                if ( !now->next[ID[word[i]]] )
                    now->next[ID[word[i]]] = newnode();
                now = now->next[ID[word[i]]];
            }
            if ( now->flag ) father[id] = now->flag;
			else now->flag = id;
        }
        void setfail() {
            Q[0] = root; root->fail = NULL;
            for ( int move = 0,save = 1 ; move < save ; ++ move ) {
                tnode* now = Q[move];
                for ( int i = 0 ; i < dictsize ; ++ i )
                    if ( now->next[i] ) {
                        tnode* p = now->fail;
                        while ( p && !p->next[i] ) p = p->fail;
                        now->next[i]->fail = p?p->next[i]:root;
                        Q[save ++] = now->next[i];
                    }
            }
        }
        void query( char* line, int q ) {
            memset( visit, 0, sizeof( visit ) );
            tnode* now = root;
            for ( int i = 0 ; line[i] ; ++ i ) {
        		while ( now && !now->next[ID[line[i]]] ) now = now->fail;
        		now = now?now->next[ID[line[i]]]:root;
                for ( tnode* p = now ; p ; p = p->fail )
                	visit[p->flag] = 1;
            }
            for ( int i = 1 ; i <= q ; ++ i )
            	if ( visit[father[i]] )
					printf("y\n");
				else printf("n\n");
            return;
        }
}dfa;
/* AC_DFA  end */

int main()
{
	int k,q;
	scanf("%d",&k);
	while ( k -- ) {
		dfa.init();

		scanf("%s%d",s,&q);
		for ( int i = 1 ; i <= q ; ++ i ) {
			scanf("%s",t);
			dfa.insert( t, i );
		}
		dfa.setfail();
		dfa.query(s, q);
	}

	return 0;
}

UVa 10679 - I Love Strings!!,布布扣,bubuko.com

时间: 2024-08-01 02:33:31

UVa 10679 - I Love Strings!!的相关文章

UVA 10679 I love Strings!!!(AC自动机)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1620 题意: 给出一个文本串和若干个模式串,问模式串是否在文本串中出现过. 分析: 简单粗暴的AC自动机模板题,要注意模式串可能有重复的情况. /* * * Author : fcbruce * * Time : Sat 04 Oct 2014 03:30:15 PM CST * */ #i

UVa OJ 455 Periodic Strings

 Periodic Strings  A character string is said to have period k if it can be formed by concatenating one or more repetitions of another string of length k. For example, the string "abcabcabcabc" has period 3, since it is formed by 4 repetitions o

UVA - 12045 Fun with Strings

题意:有一个非空字符串S1只含有字符"a","b".可将Si变为S(i+1),方法是将Si中的a全部变换为b,将b全部变换为a.现在给出了Sn和Sm的长度,分别为L1, L2,并且知道n, m,问是否存在一个合理的S1,如果存在, 求Sk的长度是多少(mod 1e9 + 7).所有变量在(0, 1e9] 范围内. 解法:设S1中含有n1个a和n2个b(n1 + n2 > 0),不难发现Si的n1和n2满足fibonacci数列性质,Si.n1 = fibo[i

UVA - 11127 Triple-Free Binary Strings dfs

题目大意:有一个字符串,这个字符串由0,1和*组成,*可以变成0也可以变成1,要求变化后的字符串的字符只能是0或者1. 现在给出这个字符串,要求变化后的字符串中不能出现三个连续相同的子串,问最多可以变化成多少个符合规则的串 解题思路:因为只有0和1,且只有30位,所以可以用一个正数来表示状态.dfs暴力枚举,边枚举边判断,看当前的是否符合 #include<cstdio> #include<cstring> using namespace std; #define maxn 35

(UVA)455 --Periodic Strings(周期串)

题目链接:http://vjudge.net/problem/UVA-455 可以从1开始枚举周期,对后面的字符逐个测试. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 int main() 7 { 8 int t; 9 char s[100]; 10 scanf("%d",&t); 11 while(t--)

UVa 10298 - Power Strings

题目:求一个串的最大的循环次数. 分析:dp,KMP,字符串.这里利用KMP算法. KMP的next函数是跳跃到最近的串的递归结构位置(串元素取值0 ~ len-1): 由KMP过程可知: 如果存在循环节,则S[0 ~ next[len]-1] 与 S[len-next[len] ~ len-1]相匹配: 则S[next[len] ~ len-1]就是循环节(且最小),否则next[len]为0: 因此,最大循环次数为len/(len-next[len]),最小循环节为S[next[len] ~

UVA - 10298 Power Strings (KMP求字符串循环节)

Description Problem D: Power Strings Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiati

UVa 10745 - Dominant Strings

题目:给你一些字符串,问哪些字符串不是其他字符串的子集,字符串的集合为字母组成的重集. 分析:字符串,dancing-links.Knuth有一篇关于dancing-links的论文,讲述关于搜索的优化. 在搜索时,将所有的状态建立一个链表,表之间的状态建立相互关系. 每次搜索时,进行剪枝,将不成立的节点从链表中删掉,回溯时在拼上去. 用数组建立链表,高效方便,存储L,R左右两端下标即可. 本题直接进行删除即可. 如果,一个字符串的补集是另一个字符串的子集,这个字符串的集合一定是另一的超集. 解

UVA 10298 - Power Strings(KMP)

UVA 10298 - Power Strings 题目链接 题意:本意其实就是,给定一个字符串,求出最小循环节需要几次循环出原字符串 思路:利用KMP中next数组的性质,n - next[n]就是最小循环节,然后n / 循环节就是答案 代码: #include <cstdio> #include <cstring> const int N = 1000005; char str[N]; int next[N]; void getnext() { int n = strlen(s