zoukankan      html  css  js  c++  java
  • JZOJ 3161. 【GDOI2013模拟2】排序(栈)

    JZOJ 3161. 【GDOI2013模拟2】排序

    Time Limits: 1000 ms Memory Limits: 32768 KB

    题目

    Description

    给你 N N N个学生的名字,要求有相同前缀的名字排在一起,具体规则如下:

    对于列表中任意两个有相同前缀的名字,排在这两个名字中间的名字也必须拥有相同的前缀。

    例如,名字MARTHA和MARY,这两个名字具有相同的前缀MAR,所以MARCO和MARVIN可以排在MARTHA和MARY之间,但MAY却不能。

    按照字典序排序肯定满足条件,但这不一定是唯一的方法,你的任务是计算出一共有多少排序方式满足要求。

    Input

    第一行输入 N ( 3 ≤ N ≤ 3000 ) N(3≤N≤3000) N(3N3000),表示名字的数量。

    接下来 N N N行,每行描述一个长度在 1 1 1 3000 3000 3000之间的大写英文字母组成的名字。

    输入保证名字互不相同。

    Output

    输出方案数 m o d    1 , 000 , 000 , 007 mod 1,000,000,007 mod1,000,000,007的值。

    Sample Input

    输入1:
    3
    IVO
    JASNA
    JOSIPA

    输入2:
    5
    MARICA
    MARTA
    MATO
    MARA
    MARTINA

    输入3:
    4
    A
    AA
    AAA
    AAAA

    Sample Output

    输出1:
    4

    输出2:
    24

    输出3:
    8

    Data Constraint

    60%的数据满足 N ≤ 10 N≤10 N10

    题解

    • 乍一看,字符串,前缀,马上想到字典树(Trie),仔细一看,发现空间似乎就是故意卡掉这种做法,
    • 不过似乎用一些神奇的方式存下这棵树是可以过的,这里就不再介绍。
    • 观察发现(题目中也说了),排序后的序列是肯定满足的,那么就先排序,
    • 用一个栈来进行操作:
    • 一、每次放入一个字符串到栈顶;
    • 二、如果栈顶两个串的最长公共前缀长度 T T T大于栈顶第一个串和还未放入栈中的第一个串的最长公共前缀长度,那么就弹栈,否则结束操作;
    • 三、把所有顶部所有最长公共前缀长度等于 T T T的全部弹出,若共弹出 x x x个数,总方案数乘上 x ! x! x!
    • 四、接着还要另外放入一个串放回栈顶,该串为上一步弹出的串的最长公共前缀去掉最后一个字符
    • 五、回到第二步。
    • 为什么?
    • 举个例子:
    • 样例2
      MARICA
      MARTA
      MATO
      MARA
      MARTINA
    • 排序后是
      MARA
      MARICA
      MARTA
      MARTINA
      MATO
    • 先放入前三个串,都不能弹栈
    • 放入第四个串后,弹出了第三、四个串, a n s ∗ 2 ! = 2 ans*2!=2 ans2!=2.
    • 另外放入一个串MAR,
    • 发现MAR和未放入的第一个串MATO最长公共前缀长度为 2 2 2,而和前面一个为 3 3 3,那么接着弹栈,
    • 可以把目前栈中所有元素弹出, a n s ∗ 3 ! = 12 ans*3!=12 ans3!=12.
    • 另外放入一个串MA,
    • 放入最后一个串后弹栈,
    • 全部弹出, a n s ∗ 2 ! = 24 ans*2!=24 ans2!=24
    • 再放回一个串M.
    • 最终答案就是 24 24 24

    代码

    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define LL long long
    #define md 1000000007
    struct node
    {
    	char p[3010];
    	int l;
    }s[3010],t[3010];
    char z[3010];
    int c[3010];
    LL f[3010];
    int check(int k,int p)
    {
    	int r=(s[k].l)<(s[0].l)?(s[k].l):(s[0].l);
    	for(int i=1;i<=r;i++)
    	{
    		if(s[k].p[i]<s[0].p[i]) return p;
    		if(s[k].p[i]>s[0].p[i]) return 1-p;
    	}
    	if(s[k].l==s[0].l) return 0;
    	if(s[k].l<s[0].l) return p; 
    	if(s[k].l>s[0].l) return 1-p;
    }
    void qsort(int l,int r)
    {
    	int x=l,y=r;
    	s[0]=s[(l+r)/2];
    	while(x<=y)
    	{
    		while(check(x,1)) x++;
    		while(check(y,0)) y--;
    		if(x<=y) s[3002]=s[x],s[x]=s[y],s[y]=s[3002],x++,y--;
    	}
    	if(x<r) qsort(x,r);
    	if(y>l) qsort(l,y);
    }
    int count(node x,node y)
    {
    	int r=(x.l)<(y.l)?(x.l):(y.l);
    	for(int i=1;i<=r;i++) if(x.p[i]!=y.p[i]) return i-1;
    	return r;
    }
    int main()
    {
    	int n,i,j;
    	scanf("%d
    ",&n);
    	for(i=1;i<=n;i++)
    	{
    		scanf("%s
    ",z+1);
    		s[i].l=strlen(z+1);
    		for(j=1;j<=s[i].l;j++) s[i].p[j]=z[j];
    	}
    	qsort(1,n);
    	t[1]=s[1];
    	int x=1;
    	LL ans=1;
    	f[0]=1;
    	for(i=1;i<=n;i++) f[i]=f[i-1]*i%md;
    	for(i=2;i<=n;i++)
    	{
    		t[++x]=s[i];
    		if(x>1)
    		{
    			int p=count(t[x],s[i+1]);
    			if(i+1>n) p=0;
    			c[x]=count(t[x],t[x-1]);
    			while(p<c[x])
    			{
    				int j=x,ss=2;
    				while(c[j-1]==c[x]) j--,ss++;
    				t[j-1].l=c[x];
    				x=j-1;
    				ans=ans*f[ss]%md;
    				c[x]=count(t[x],t[x-1]);
    				p=count(t[x],s[i+1]);
    				if(i+1>n) p=0;
    			}
    		}
    	}
    	ans=ans*f[x]%md;
    	printf("%lld",ans);
    	return 0;
    }
    
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    web前端的发展态势
    AngularJs 简单入门
    css代码优化篇
    git提交报错:Please make sure you have the correct access rights and the repository exists.
    Activiti工作流框架学习
    遍历map集合的4种方法
    js设置日期、月份增加减少
    Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    webservice_rest接口_学习笔记
    相互匹配两个list集合+动态匹配${}参数
  • 原文地址:https://www.cnblogs.com/LZA119/p/13910083.html
Copyright © 2011-2022 走看看