zoukankan      html  css  js  c++  java
  • 【2020.12.02提高组模拟】球员(player) 题解

    【2020.12.02提高组模拟】球员(player) 题解

    题意描述

    基本的递推。

    ①所有运动员姓氏的长度必须不同。

    ②每个运动员的姓氏必须是长度比其长的所有其他运动员姓氏的连续子串

    潜在的球员分成 (N) 类,第(i)类的球员的姓氏恰好有(i)个字母,且每一类恰好有(K)个球员。 有多少种不同的方法选出满足要求的$ N $个球员。答案对(10^9+7)取余。

    Solution

    先抛开字符串,思考(DP).

    (f[i][j])表示第(i)类运动员中的第(j)个与其前面的(i-1)类运动员有多少种匹配方案。

    那么

    [f[i][j]=sum_{t=1}^{k}[s[i-1][t]是s[i][j]的一部分]f[i-1][t]\ f[1][j]=1 ]

    那么我们需要(O(nk))枚举,再(O(k))枚举上一层,再(O(n))判断两个字符串是否为包含关系,总时间复杂度为(O(n^2k^2))

    优化,用(哈希)或者(AC自动机)(map)即可,时间复杂度取决于你用什么。

    (trie)的话貌似会被卡呢(笑)

    Code

    /*
    	Name: 
    	Copyright: iee
    	Author: hsh778205
    	Date: 02/12/20 10:04
    	Description: time O(n^2klog(nk)),memory O(n^2k+?)
    */
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include<set>
    #include<queue>
    #include<vector>
    #define IL inline
    #define re register
    #define LL long long
    #define ULL unsigned long long
    #ifdef TH
    #define debug printf("Now is %d
    ",__LINE__);
    #else
    #define debug
    #endif
    using namespace std;
    inline int read()
    {
    	int x=0,fu=1;
    	char ch=getchar();
    	while(!isdigit(ch)&&ch!='-') ch=getchar();
    	if(ch=='-') fu=-1,ch=getchar();
    	x=ch-'0';ch=getchar();
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	return x*fu;
    }
    int G[55];
    template<class T>inline void write(T x)
    {
    	int g=0;
    	if(x<0) x=-x,putchar('-');
    	do{G[++g]=x%10;x/=10;}while(x);
    	for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('
    ');
    }
    #define p 1000000007
    map<string,LL>m;
    int n,k,i,j;
    LL ans;
    string str[51][1510],t1,t2;
    int main()
    {
    //	freopen("player.in","r",stdin);
    //	freopen("player.out","w",stdout);
    	n=read();
    	k=read();
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<=k;j++)
    		{
    			cin>>str[i][j];
    		}
    	}
    	for(i=1;i<=k;i++) m[str[1][i]]++;
    	for(i=2;i<=n;i++)
    	{
    		for(j=1;j<=k;j++)
    		{
    			t1=str[i][j].substr(0,str[i][j].size()-1);
    			t2=str[i][j].substr(1);
    			if(m.find(t1)!=m.end()) m[str[i][j]]=(m[str[i][j]]+m[t1])%p;
    			if(t1!=t2) if(m.find(t2)!=m.end()) m[str[i][j]]=(m[str[i][j]]+m[t2])%p;
    		}
    	}
    	for(i=1;i<=k;i++)
    	{
    		ans=(ans+m[str[n][i]])%p;
    		m[str[n][i]]=0;
    	}
    	write(ans);
    	return 0;
    }
    
  • 相关阅读:
    【杭电】[2071]Max Num
    【POJ】[1679]The Unique MST
    【POJ】[1679]The Unique MST
    Mac 系统引导过程概述 & BootCamp 的秘密
    Mac 系统引导过程概述 & BootCamp 的秘密
    在Eclipse中参看项目中的所有文件
    在Eclipse中参看项目中的所有文件
    让Eclipse不仅仅只是通过点号来激活代码提示功能
    让Eclipse不仅仅只是通过点号来激活代码提示功能
    Eclipse汉化包的下载和安装
  • 原文地址:https://www.cnblogs.com/send-off-a-friend/p/14074365.html
Copyright © 2011-2022 走看看