zoukankan      html  css  js  c++  java
  • [后缀自动机] hihoCoder 1145

    (刷的第一道后缀自动机)

    正式开始后缀自动机的漫长道路

    hihoCoder 1145

    时间限制:10000ms
    单点时限:2000ms
    内存限制:512MB

    描述

    小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。

    现在小Hi想知道一部作品中出现了多少不同的旋律?

    输入

    共一行,包含一个由小写字母构成的字符串。字符串长度不超过 1000000。

    输出

    一行一个整数,表示答案。

    样例输入
    aab
    样例输出
        5
    思路:
      对所有状态st求Σ(maxlen(st)-minlen(st))(模板自带-1所以这里不用,到时候更懂的时候补充)

      裸题,建完图后直接求就行了
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e6+5;;
    char s[maxn]; 
    struct Sam {
    	int next[maxn << 1][26];
    	int link[maxn << 1], step[maxn << 1];//step 
    	int a[maxn], b[maxn << 1];
    	int sz, last, root;
    	void init() {
    		//如多次建立自动机,加入memset操作
    		root = sz = last = 1;
    	}
    	void add(int c) {
    		int p = last;
    		int np = ++sz;
    		last = np;
    		step[np] = step[p] + 1;
    		while(!next[p][c] && p) {
    			next[p][c] = np;
    			p = link[p];
    		}
    		if(p == 0) {
    			link[np] = root;
    		} else {
    			int q = next[p][c];
    			if(step[p] + 1 == step[q]) {
    				link[np] = q;
    			} else {
    				int nq = ++sz;
    				memcpy(next[nq], next[q], sizeof(next[q]));
    				step[nq] = step[p] + 1;
    				link[nq] = link[q];
    				link[q] = link[np] = nq;
    				while(next[p][c] == q && p) {
    					next[p][c] = nq;
    					p = link[p];
    				}
    			}
    		}
    	}
    	void build() {
    		init();
    		for(int i = 0; s[i]; i++) {
    			add(s[i] - 'a');
    		}
    		for(int i = 1; i <= sz; i++) {
    			a[step[i]]++;
    		}
    		for(int i = 1; i <= step[last]; i++) {
    			a[i] += a[i - 1];
    		}
    		for(int i = 1; i <= sz; i++) {
    			b[a[step[i]]--] = i;
    		}
    	}
    } sam;
    int main()
    {
    	cin>>s;
    	long long ans = 0;
    	sam.build();
    	for(int i = 1;i<=sam.sz;i++)
    	{
    		ans+=sam.step[i]-sam.step[sam.link[i]];
    	//	cout<<ans<<" += "<<sam.step[i]<<" - "<<sam.step[sam.link[i]]<<endl;
    	}
    	cout<<ans<<endl;
    } 
    

      

  • 相关阅读:
    数组中的逆序对
    第一个只出现一次的字符
    丑数
    把数组排成最小的数
    整数中出现1的个数
    连续子数组最大和
    JS之window对象
    JS之递归(例题:猴子吃桃)
    JS中函数的基础知识
    JS数组2(冒泡排列、数组里面查找数据)
  • 原文地址:https://www.cnblogs.com/kgs719/p/9853692.html
Copyright © 2011-2022 走看看