• 【BZOJ 3172】单词


    【链接】h在这里写链接


    【题意】


        给你n个单词;
        这n个单词组成了一篇文章;
        问你每个单词在这篇文章中出现了多少次.
        其中每个单词之间用一个逗号隔开->组成一篇文章。
        (单词的总长度不会超过10^6)
        单词的个数小于等于200


    【题解】


        后缀数组题.
        把每个字符串用一个分隔符分开来.
        然后求其后缀数组;

        然后先获取每个单词后缀的排名;
        然后往左走直到lcp小于这个单词的长度,
        然后往右走直到lcp小于这个单词的长度
        向左走和向右走的区间就是这个单词在文章中出现的次数。

        暴力做一下就好;
        如果想优化的话,感觉可以再加一个二分。
        因为长度越长,显然lcp是越来越小的。。
        啦啦啦
        但是不用加这个优化就可以过啦。
        听网上的人说的。。


    【错的次数】


    0

    【反思】


    在这了写反思

    【代码】

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 1e6 + 500;
    const int MAX_CHAR = 500;//每个数字的最大值。
    int s[N + 10];//如果是数字,就写成int s[N+10]就好,从0开始存
    int Sa[N + 10], T1[N + 10], T2[N + 10], C[N + 10];
    int Height[N + 10], Rank[N + 10];
    
    void build_Sa(int n, int m) {
    	int i, *x = T1, *y = T2;
    	for (i = 0; i<m; i++) C[i] = 0;
    	for (i = 0; i<n; i++) C[x[i] = s[i]]++;
    	for (i = 1; i<m; i++) C[i] += C[i - 1];
    	for (i = n - 1; i >= 0; i--) Sa[--C[x[i]]] = i;
    	for (int k = 1; k <= n; k <<= 1)
    	{
    		int p = 0;
    		for (i = n - k; i<n; i++) y[p++] = i;
    		for (i = 0; i<n; i++) if (Sa[i] >= k) y[p++] = Sa[i] - k;
    		for (i = 0; i<m; i++) C[i] = 0;
    		for (i = 0; i<n; i++) C[x[y[i]]]++;
    		for (i = 1; i<m; i++) C[i] += C[i - 1];
    		for (i = n - 1; i >= 0; i--) Sa[--C[x[y[i]]]] = y[i];
    		swap(x, y);
    		p = 1; x[Sa[0]] = 0;
    		for (i = 1; i<n; i++)
    			x[Sa[i]] = y[Sa[i - 1]] == y[Sa[i]] && y[Sa[i - 1] + k] == y[Sa[i] + k] ? p - 1 : p++;
    		if (p >= n) break;
    		m = p;
    	}
    }
    
    void getHeight(int n)
    {
    	int i, j, k = 0;
    	for (i = 1; i <= n; i++) Rank[Sa[i]] = i;
    	for (i = 0; i<n; i++) {
    		if (k) k--;
    		j = Sa[Rank[i] - 1];
    		while (s[i + k] == s[j + k]) k++;
    		Height[Rank[i]] = k;
    	}
    }
    
    int n, fir[200 + 10],le[200+10];
    char ts[N + 10];
    
    int main() 
    {
    	//freopen("F:\rush.txt", "r", stdin);
    	int t;
    	scanf("%d", &t);
    	for (int ii = 1;ii <= t;ii++)
    	{
    		scanf("%s", ts);
    		int len = strlen(ts);
    		le[ii] = len;
    		fir[ii] = n;
    		for (int i = 0; i < len; i++)
    			s[n++] = ts[i];
    		s[n++] = 'z' + ii;//不能是字符类型,可能会爆掉!
    	}
    	s[n] = 0;
    	build_Sa(n + 1, MAX_CHAR);//注意调用n+1
    	getHeight(n);
    	for (int i = 1; i <= t; i++)
    	{
    		int temp = Rank[fir[i]],temp1 = temp,ans = 1;
    		while (temp - 1 >= 1 && Height[temp] >= le[i])
    		{
    			ans++;
    			temp--;
    		}
    		while (temp1 + 1 <= n && Height[temp1 + 1] >= le[i])
    		{
    			ans++;
    			temp1++;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }


  • 相关阅读:
    C# 规格说明书
    C#学习笔记----复习笔记
    C#学习笔记-stream,win8.1开发小记
    C#学习笔记-Win8.1 store app winform开发小记
    C#学习笔记:linq和xml
    C#第六周--关于正则表达式应用,delegates关键字
    C#第六课---struct,interface
    C#第五课--继承和多态
    开发了一款小程序
    「CSS Warning 2」icon 的做法
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7625980.html
Copyright © 2020-2023  润新知