• [SDOI2007]游戏


    XXX.[SDOI2007]游戏

    STL的百种用法

    可以观察到可以接龙的对构成一张DAG。因此我们要找到DAG中最长路。这个随便DP就可以了。

    关键是找到可以互相转移的位置。

    \(n^2\)枚举非常危险,因为还有一个\(26\)判断的常数,没试,估计过不了。

    我们必须寻找复杂度更低的算法。

    发现一个串只与组成它的每个字符的数量有关。那么我们可以把这每个字符的数量压到一个vector里面,然后用map<vector<int>,int>来找可以转移的位置。或者因为串长\(\leq 100\),因此vector中每个数必定不超过\(100\),然后可以化成一个string。当然,string也可以哈希(虽然答案就不一定正确了)。

    当然,无论怎么搞,都有一个\(26\)的常数(似乎哈希一下复杂度是\(26n\log n\),而不哈希复杂度是\(26^2\log n\))。但不管怎么说,能过。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    string s[10010];
    map<vector<int>,int>m;
    int S,n,f[10010],pre[10010],mp;
    void print(int i){
    	if(!i)return;
    	print(pre[i]);
    	cout<<s[i]<<endl;
    }
    int main(){
    	n++;
    	while(cin>>s[n])n++;
    	sort(s+1,s+n);
    	for(int i=1;i<n;i++){
    		f[i]=1;
    		vector<int>v;
    		v.resize(26);
    		for(auto j:s[i])v[j-'a']++;
    		m[v]=i;
    	}
    	for(auto i:m){
    		vector<int>v=i.first;
    		for(int k=0;k<26;k++){
    			v[k]++;
    			if(m.find(v)!=m.end()){
    				int j=m[v];
    				if(f[j]<f[i.second]+1)f[j]=f[i.second]+1,pre[j]=i.second;
    			}
    			v[k]--;
    		}
    	}
    	for(int i=1;i<n;i++)if(f[i]>f[mp])mp=i;
    	printf("%d\n",f[mp]);
    	print(mp);
    	return 0;
    }
    

  • 相关阅读:
    查询详细信息和删除记录
    软件开发过程中常用到的一些工具
    无服务器端的UDP群聊功能剖析(WCF版)
    vim插件使用
    C#中ConnectionStrings和AppSettings的区别
    《Effective C++》简明笔记上
    设计模式的一些所想所得
    对RESTful Web API的理解与设计思路
    js加载脚
    OSGi.NET 学习笔记 [模块可扩展支持][概念][实例]
  • 原文地址:https://www.cnblogs.com/Troverld/p/14597082.html
Copyright © 2020-2023  润新知