[SPOJ-BEADS]Glass Beads

 

来源:
  CE1998

题目大意:
  求字符串最小表示。

思路:
  字符串复制一遍接在后面,构建SAM,然后每次跑小的转移。
  跑n次以后就跑到了最小表示的末尾,用该状态的len值减去n就是最小表示的起始位置。

 1 #include<string>
 2 #include<iostream>
 3 int n;
 4 std::string s;
 5 class SuffixAutomaton {
 6     private:
 7         static const int SIGMA_SIZE=26;
 8         struct State {
 9             State *link,*trans[SIGMA_SIZE];
10             unsigned len,min_trans;
11             State(const int l) {
12                 link=nullptr;
13                 std::fill(&trans[0],&trans[SIGMA_SIZE],nullptr);
14                 min_trans=SIGMA_SIZE;
15                 len=l;
16             }
17         };
18         State *root,*last;
19         unsigned idx(const int ch) {
20             return ch-'a';
21         }
22         void extend(const char ch) {
23             const unsigned w=idx(ch);
24             State *p=last,*new_p=new State(last->len+1);
25             while(p!=nullptr&&p->trans[w]==nullptr) {
26                 p->trans[w]=new_p;
27                 p->min_trans=std::min(p->min_trans,w);
28                 p=p->link;
29             }
30             if(p==nullptr) {
31                 new_p->link=root;
32             } else {
33                 State *q=p->trans[w];
34                 if(q->len==p->len+1) {
35                     new_p->link=q;
36                 } else {
37                     State *new_q=new State(p->len+1);
38                     std::copy(&q->trans[0],&q->trans[SIGMA_SIZE],new_q->trans);
39                     new_q->min_trans=q->min_trans;
40                     new_q->link=q->link;
41                     q->link=new_p->link=new_q;
42                     while(p!=nullptr&&p->trans[w]==q) {
43                         p->trans[w]=new_q;
44                         p=p->link;
45                     }
46                 }
47             }
48             last=new_p;
49         }
50     public:
51         void build() {
52             root=last=new State(0);
53             for(std::string::iterator i=s.begin();i<s.end();i++) {
54                 extend(*i);
55             }
56             for(std::string::iterator i=s.begin();i<s.end();i++) {
57                 extend(*i);
58             }
59         }
60         unsigned query() {
61             State *p=root;
62             for(unsigned i=0;i<s.length();i++) {
63                 p=p->trans[p->min_trans];
64             }
65             return p->len-s.length()+1;
66         }
67 };
68 SuffixAutomaton sam;
69 int main() {
70     std::ios_base::sync_with_stdio(false);
71     std::cin.tie(NULL);
72     std::cin>>n;
73     for(int i=0;i<n;i++) {
74         std::cin>>s;
75         sam.build();
76         std::cout<<sam.query()<<std::endl; 
77     }
78     return 0;
79 }

 

转载于:https://www.cnblogs.com/skylee03/p/7526748.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值