HDU - 3407 - String-Matching Automata

先上题目:

String-Matching Automata

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 215    Accepted Submission(s): 140


Problem Description
The finite state automaton (FSA) is an important model of behavioral investigations in computer science, linguistics and many other areas. A FSA can be typically modeled as a string pattern recognizer described by a quintuple <Σ, S, s0, δ, F>, where:

Σ is the input alphabet (a finite nonempty set of symbols).
S is a finite nonempty set of states.
s0 is an element in S designated as the initial state.
δ is a function δ: S × Σ → S known as the transition function.
F is a (possibly empty) subset of S whose elements are designated as the final states.

An FSA with the above description operates as follows:

At the beginning, the automaton starts in the initial state s0.
The automaton continuously reads symbols from its input, one symbol at a time, and transits between states according to the transition function δ. To be specific, let s be the current state and w the symbol just read, the automaton moves to the state given by δ(s, w).
When the automaton reaches the end of the input, if the current state belongs to F, the string consisting sequentially of the symbols read by the automaton is declared accepted, otherwise it is declared rejected.

Just as the name implies, a string-matching automaton is a FSA that is used for string matching and is very efficient: they examine each character exactly once, taking constant time per text character. The matching time used (after the automaton is built) is therefore Θ(n). However, the time to build the automaton can be large.

Precisely, there is a string-matching automaton for every pattern P that you search for in a given text string T. For a given pattern of length m, the corresponding automaton has (m + 1) states {q0, q1, …, qm}: q0 is the start state, qm is the only final state, and for each i in {0, 1, …, m}, if the automaton reaches state qi, it means the length of the longest prefix of P that is also a suffix of the input string is i. When we reaches state qm, it means P is a suffix of the currently input string, which suggest we find an occurrence of P.

The following graph shows a string-matching automaton for the pattern “ababaca”, and illustrates how the automaton works given an input string “abababacaba”.



Apparently, the matching process using string-matching automata is quite simple (also efficient). However, building the automaton efficiently seems to be tough, and that’s your task in this problem.
 

 

Input
Several lines, each line has one pattern consist of only lowercase alphabetic characters. The length of the longest pattern is 10000. The input ends with a separate line of ‘0’.
 

 

Output
For each pattern, output should contain (m + 1) lines(m is the length of the pattern). The nth line describes how the automaton changes its state from state (n-1) after reading a character. It starts with the state number (n – 1), and then 26 state numbers follow. The 1st state number p1 indicates that when the automaton is in state (n-1), it will transit to state p1 after reading a character ‘a’. The 2nd state number p2 indicates that when the automaton is in state (n-1), it will transit to state p2 after reading a character ‘b’… And so on.
 

 

Sample Input
ababaca 0
 

 

Sample Output
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 1 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 1 4 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
6 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 
Source
 
  题意:给你一个串,问你当匹配到某个位置的时候如果当匹配的字母为'a'-'z'的时候分别需要转移的位置是哪里?
 
  解法可以用KMP+一点其他操作。另一种方法是直接写一个AC自动机,然后build了自动机以后就沿着Trie树上输入的单词对于某一个节点就直接打印这个节点的next[i]['a'~'z']就可以了。
 
上代码:
 
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #define MAX 10002
 5 using namespace std;
 6 
 7 struct Trie{
 8     int next[MAX][26],fail[MAX],end[MAX],num[MAX][26];
 9     int root,L;
10 
11     int newnode(){
12         for(int i=0;i<26;i++){ next[L][i]=-1; num[L][i]=0;}
13         end[L++]=0;
14         return L-1;
15     }
16     void init(){
17         L=0;    root=newnode();
18     }
19 
20     void insert(char buf[]){
21         int len=strlen(buf);
22         int now = root;
23         for(int i=0;i<len;i++){
24             if(next[now][buf[i]-'a']==-1){
25                 next[now][buf[i]-'a']=newnode();
26 
27             }
28             now=next[now][buf[i]-'a'];
29         }
30         end[now]++;
31     }
32 
33     void build(){
34         queue<int> Q;
35         fail[root]=root;
36         for(int i=0;i<26;i++){
37             if(next[root][i]==-1) next[root][i]=root;
38             else{
39                 fail[next[root][i]]=root;
40                 Q.push(next[root][i]);
41             }
42         }
43         while(!Q.empty()){
44             int now=Q.front();
45             Q.pop();
46             for(int i=0;i<26;i++){
47                 if(next[now][i]==-1) next[now][i]=next[fail[now]][i];
48                 else{
49                     fail[next[now][i]]=next[fail[now]][i];
50                     Q.push(next[now][i]);
51                 }
52             }
53         }
54     }
55 
56     void print(char buf[]){
57         int len=strlen(buf);
58         int now=root;
59         for(int i=0;i<=len;i++){
60             printf("%d",i);
61             for(int j=0;j<26;j++) printf(" %d",next[now][j]);
62             printf("\n");
63             now=next[now][buf[i]-'a'];
64         }
65     }
66 };
67 
68 Trie ac;
69 char s[MAX];
70 
71 int main()
72 {
73     //freopen("data.txt","r",stdin);
74     while(scanf("%s",s),strcmp(s,"0")){
75         ac.init();
76         ac.insert(s);
77         ac.build();
78         ac.print(s);//printf("\n");
79     }
80     return 0;
81 }
/*3407*/

 

 

转载于:https://www.cnblogs.com/sineatos/p/3946734.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值