zoukankan      html  css  js  c++  java
  • POJ2525Text Formalization

    转载请注明出处:優YoU http://blog.csdn.net/lyy289065406/article/details/6746954

    大致题意:

           首先说明,下面所述的“大致题意”并不是题目的原意,但是按照题目原意去做是不可能AC的,因为测试数据库与题目原意出入非常大。另外顺便建议,刚玩POJ的同学没事不要做这题,因为如果没有测试数据库你会疯掉的,有测试数据库也很容易疯掉的。

           有两种类型的字符串,分别为Contraction和Acronym,它们都有其扩展形式Expand。现在给出C个Contraction和A个Acronym的扩展形式,格式如下:

    "contraction or acronym" -> "expansion"

    其中红色部分,引号和箭号之间可能有空格,可能无空格。

    然后再给出数篇Text每篇Text用一个独占一行的#分隔(注意若有数个#连续出现,则不是分隔符),而且每篇Text都包含有数行,每行的长度最多为80。

    要求把每篇Text出现Contraction和Acronym的位置都分别用其扩展式替换,然后重新输出扩展后的Text。

    关于扩展:

    1、  Contraction

    Contraction在Text中有3种表现形式,按照优先级分别为"as listed,"(原型) "uppercased,"(尽数大写) 和 "capitalized."(首字母大写)。

           举例说明: 给定Contraction为isn’t,其扩展式为is not

           那么在检测Text时,若检测到isn’t,则替换为is not

                                         若检测到ISN’T,则替换为IS NOT

                                         若检测到Isn’t,则替换为Is not

    若检测到诸如IsN’t的其他串,由于不属于以上3种情况的任意一种,则不替换,直接输出原串。

    注意:

    (a)3种形式必须根据优先级检测,即若有"as listed,",则不能替换为"uppercased,"或"capitalized." ;若有"uppercased,"则不能替换为"capitalized."。

    (b)扩展式与Contraction的表现形式必须一致。

    2、Acronym

           Acronym在Text中只有一种表现形式,就是"as listed,",但替换时有2个特殊要求:

    (a)       对于同一篇Text,Acronym只能被替换1次,且替换的位置为其第一次出现的位置,其他位置不替换。

    (b)       替换Acronym的时候,必须在其替换式的最后加上“空格(Acronym原型)”。

    例如:给定Acronym为CS,其扩展式为Computing Science

    那么应该把Text中的CS替换为 Computing Science (CS)

    3、非字母串的Contraction与Acronym

           前2点都是在Contraction与Acronym都是由字母组成的基础上的替换模式。

           当Contraction或Acronym由非字母的字符串构成时,其扩展式只有"as listed,"一种形式,而Acronym替换后依然要加上“空格(Acronym原型)”。

    例如:

    (a)给定的Contraction为 <!=> ,其扩展式为a-c+d

    那么在Text检测到<!=>就直接替换为a-c+d,无大小写之分。

    (b)       给定Acronym为&&&,其扩展式为 **rr!!$

    那么在Text检测到&&&就直接替换为**rr!!$ (&&&)

    4、Contraction与Acronym可以是任意字符串的前缀或后缀,依然要替换

    5、不能迭代替换,就是说只能针对原本属于Text的字符串替换,不能对扩展后的Expand串替换

    解题思路:

    其实如果原题题意和测试数据库的测试项是一致的话,这题是很简单的模拟题,字符串替换而已,不应该放到“高级题”里面。

    原题题意故意误导的错误信息有3点:(注意下面是错误信息)

    1、  Contraction与Acronym不是任何单词的前缀或后缀

    2、  Text是规范的字母串+标点

    3、"contraction or acronym" -> "expansion" 红色部分两引号间固定有2个空格

    而从测试数据库真正反应出来的信息是:(注意下面是正确信息)

    1、Contraction与Acronym可以是任何字符(串)的前缀或后缀

    2、Text纯粹是一些字符串的组合

    3、"contraction or acronym" -> "expansion"红色部分两个引号之间的空格数目不固定

    明白到上面所述,本题的处理就很简单了。由于要匹配的字符串很多,因此本题用TrieTree的效率是最高的, hash很可能会超时。

    1、  把Contraction与Acronym录入到TrieTree,这里的TrieTree要做一个简单的变形,就是原本在结点中用于标记单词的布尔量flag,改为整型id,id=0表示从TrieTree到当前结点的字符串不是Contraction或Acronym; id>0表示TrieTree到当前结点的字符串是Contraction或Acronym,并且id就是其扩展式的映射。

    2、  建立扩展串二维数组,行为id,对应的行就是Contraction或Acronym的扩展式。

    3、  下面称上述2步为“字典录入”,字典录入的时候,在录入Contraction时,顺便同时录入其3种形式,而且必须按照优先顺序录入id。而这样录入可能会导致后面录入时出现重复,为了保证优先性,若在录入某个Contraction或Acronym时,该位置的id已经不为0,则跳过不录入,避免优先级低的扩展串替换了优先级高的扩展串。

    4、  在录入Acronym的时候,当存放其扩展串都Expand时,顺便把“空格(Acronym原型)”放到其扩展串末尾。

    5、  因此检测Text时,对Acronym的id设置标记是否扩展过一次,扩展过的不再扩展,当读入下一篇Text时(#号),标记清零。

    6、  对Text逐行读入,逐行替换后输出。由于Contraction与Acronym可以是任意字符串的前缀或后缀,对每一行的检测应该逐个字符检测,即对于字符c,若TrieTree中以c为首的字符串的分支指针均为NULL,则直接输出c,否则递归检查其是否为Contraction或Acronym,若是则替换,若不是依然直接输出c,继续检测下一字符。

    Source修正

    Alberta Collegiate Programming Contest 2003.10.18

    http://ugweb.cs.ualberta.ca/~acpc/2003/

    //Memory Time 
    //692K   32MS 
    
    #include<iostream>
    #include<cmath>
    using namespace std;
    
    struct Trie_Node   //TrieTree结点
    {
    	int id;					//标记从Root到当前Node的字符串是否为单词
    							//id为该单词录入TrieTree的顺序编号, id=0表示该单词不存在
    	int len;				//单词长度
    	Trie_Node* next[128];	//分支,规模为未扩展ASCII的字符数
    };
    
    class solve
    {
    public:
    	solve(int c,int a):C(c),A(a)
    	{
    		id=0;
    		Trie_Node* Root=new Trie_Node;		//构造TrieTree的根结点
    		initial(Root);						//初始化根结点
    
    		Expand=new char*[C*3+A+1];			//申请扩展串的空间
    		for(int i=1;i<=C*3+A;i++)
    			Expand[i]=new char[StrSize()];
    
    		EntryWord(Root);					//录入每个串的扩展串(字典登记)
    		ReadText(Root);						//扩展文章
    	}
    	~solve()
    	{
    		for(int i=1;i<=C*3+A;i++)
    			delete[] Expand[i];
    	}
    
    	int StrSize(void) const{return 81;}		//字符串的长度尺寸
    	char UppAlp(char c);					//c若为小写字母,返回其大写;若为其他字符,返回其本身
    
    	void initial(Trie_Node* p);				//初始化TireTree的结点
    	void EntryWord(Trie_Node* Root);		//录入每个串的扩展串(字典登记),并把其id映射到扩展串数组Expand
    	void ReadText(Trie_Node* Root);			//逐行读入Text,逐行扩展输出
    	
    protected:
    
    	int C;			//Contraction数量
    	int A;			//Acronym数量
    	int id;			//录入TrieTree的单词的顺序编号
    	int KeyId;		//顺序编号<=KeyId的单词为Contraction ,顺序编号>KeyId的单词为Acronym
    	char** Expand;	//记录Contraction和Acronym的扩展串,用id作为映射
    };
    
    void solve::initial(Trie_Node* p)
    {
    	p->id=0;
    	p->len=0;
    	memset(p->next,0,sizeof(p->next));
    	return;
    }
    
    void solve::EntryWord(Trie_Node* Root)  
    {
    	int i,j,k;		//temporary
    	char tc;
    
    	/*录入Contraction到Trieree,同时录入其3种形式*/
    
    	for(i=1;i<=C;i++)
    	{
    		Trie_Node* p1=Root;		//at list
    		Trie_Node* p3=Root;		//uppercased
    		Trie_Node* p2=Root;		//capitalized
    		bool flag1=false,flag2=false,flag3=false;	//优先级标记,已录入扩展串的id不会被覆盖
    
    		char Tmps[200];
    		gets(Tmps);
    
    		for(j=1;Tmps[j]!='\"';j++)
    		{
    			//at list
    			if(!p1->next[Tmps[j]])
    			{
    				p1->next[Tmps[j]]=new Trie_Node;
    				initial(p1->next[Tmps[j]]);
    			}
    			p1->next[Tmps[j]]->len = p1->len+1;
    			p1 = p1->next[Tmps[j]];
    
    			//uppercased
    			tc=UppAlp(Tmps[j]);
    			if(!p2->next[tc])
    			{
    				p2->next[tc]=new Trie_Node;
    				initial(p2->next[tc]);
    			}
    			p2->next[tc]->len = p2->len+1;
    			p2 = p2->next[tc];
    
    			//capitalized
    			tc=(j==1?UppAlp(Tmps[j]):Tmps[j]);
    			if(!p3->next[tc])
    			{
    				p3->next[tc]=new Trie_Node;
    				initial(p3->next[tc]);
    			}
    			p3->next[tc]->len = p3->len+1;
    			p3=p3->next[tc];
    		}
    
    		//录入编号,建立缩写与扩展形式的映射
    		//由于优先原则,若id此前已登记到TrieTree,则以后均不登记
    		if(p1->id)
    			flag1=true;
    		else
    			p1->id=++id;	
    		
    		if(p2->id)
    			flag2=true;
    		else
    			p2->id=++id;
    
    		if(p3->id)
    			flag3=true;
    		else
    			p3->id=++id;
    
    		/*录入Contraction的扩展形式到Expand*/
    
    		while(Tmps[++j]!='\"');		//跳过 "->" 部分
    		k=j+1;
    		for(j=0;Tmps[k]!='\"';k++,j++)
    		{
    			//at list
    			if(!flag1)
    				Expand[p1->id][j]=Tmps[k];
    
    			//uppercased
    			if(!flag2)
    				Expand[p2->id][j]=UppAlp(Tmps[k]);
    
    			//capitalized
    			if(!flag3)
    			{
    				if(j==0)
    					Expand[p3->id][j]=UppAlp(Tmps[k]);
    				else
    					Expand[p3->id][j]=Tmps[k];
    			}
    		}
    		if(!flag1)
    			Expand[p1->id][j]='\0';
    		
    		if(!flag2)
    			Expand[p2->id][j]='\0';
    
    		if(!flag3)
    			Expand[p3->id][j]='\0';
    	}
    
    	/*录入Acronym到Trieree*/
    
    	KeyId=id;		//分界点编号登记
    
    	for(i=1;i<=A;i++)
    	{
    		Trie_Node* p=Root;
    		bool flag=false;
    
    		char Tmps[200];
    		gets(Tmps);
    
    		for(j=1;Tmps[j]!='\"';j++)
    		{
    			if(!p->next[Tmps[j]])
    			{
    				p->next[Tmps[j]]=new Trie_Node;
    				initial(p->next[Tmps[j]]);
    			}
    			p->next[Tmps[j]]->len = p->len+1;
    			p = p->next[Tmps[j]];
    		}
    		if(p->id)
    			flag=true;
    		else
    			p->id=++id;
    
    		/*录入Acronym的扩展形式到Expand*/
    		
    		if(!flag)
    		{
    			while(Tmps[++j]!='\"');
    			k=j+1;
    			for(j=0;Tmps[k]!='\"';k++,j++)
    				Expand[p->id][j]=Tmps[k];
    
    			//Acronym的扩展串要求在最后加上" (Acronym)"
    			Expand[id][j++]=' ';
    			Expand[id][j++]='(';
    
    			for(k=1;Tmps[k]!='\"';k++)
    				Expand[id][j++]=Tmps[k];
    
    			Expand[id][j++]=')';
    			Expand[id][j]='\0';
    		}
    	}
        return;
    }
    
    void solve::ReadText(Trie_Node* Root)
    {
    	int i,j,f;
    
    	bool* FirstApp;		//标记Acronym是否已经扩展过一次
    	FirstApp=new bool[id+1];
    	for(f=KeyId+1;f<=id;f++)
    		FirstApp[f]=false;
    
    	char* line=new char[StrSize()];
    	while(gets(line))	//逐行输入文章
    	{
    		for(i=0;line[i];i++)
    		{
    			/*文章结束符*/
    			if(line[i]=='#' && line[i+1]!='#')
    			{
    				printf("#");
    				for(f=KeyId+1;f<=id;f++)	//清空acronym首次出现的标记
    					FirstApp[f]=false;
    
    				break;
    			}
    
    			Trie_Node* p=Root;
    
    			//以当前字符line[i]为首的单词没有登记到TrieTree,直接输出
    			if(!p->next[ line[i] ])	
    			{
    				printf("%c",line[i]);
    				continue;
    			}
    
    			//以当前字符line[i]为首的单词可能有登记到TrieTree,检查后续字符是否构成单词
    			for(j=i;!p->id;j++)
    			{
    				if(p->next[line[j]])
    					p=p->next[line[j]];
    				else
    					break;
    			}
    			if(p->id!=0)	
    			{
    				if(p->id <= KeyId)		//以字符line[i]为首的单词为Contraction
    				{
    					printf("%s",Expand[p->id]);
    					i+=p->len-1;
    				}
    				else if(p->id>KeyId && !FirstApp[p->id])//以字符line[i]为首的单词为Acronym
    				{										//且在当前Text从未被扩展过
    					FirstApp[p->id]=true;
    					printf("%s",Expand[p->id]);
    					i+=p->len-1;
    				}
    				else if(p->id>KeyId && FirstApp[p->id])//以字符line[i]为首的单词为Acronym
    				{										//且在当前Text已被扩展过,直接输出line[i]
    					printf("%c",line[i]);
    				}
    			}
    			else	//以字符line[i]为首的单词均未登记到TrieTree,直接输出line[i]
    			{
    				printf("%c",line[i]);
    			}
    		}
    		printf("\n");	//文章Text每行换行
    	}
    
    	delete[] FirstApp;
    	return;
    }
    
    char solve::UppAlp(char c)
    {
    	if(c<'a' || c>'z')
    		return c;
    
    	return c-32;
    }
    
    int main(void)  
    {
    	int c,a;
    	scanf("%d %d",&c,&a);
    	getchar();		//下次输入函数为gets(),则此处要吃掉回车符
    
    	solve poj2525(c,a);
    
    	return 0;
    }
    

    Sample Input-1

    3 2

    "doesn't" -> "does not"

    "isn't" -> "is not"

    "can't" -> "cannot"

    "ACM" -> "Association for Computing Machinery"

    "CS" -> "Computing Science"

    #

    ACM ACM ACM

    #

    The ACM can't solve Can't CAN'T solve CaN't solve

    all the problems in CS. Though large and having

    many resources at its disposal, the ACM doesn't use magic. Magic isn't

    part of science, and hence not part of CS. Thank you for your

    suggestions.

    Signed, ACM

    #

    doesn'tisn'tcan'tACMCS

    #

    The ACM doesn't like magic.

    #

    It's not that the ACM won't use it, it's

    #

    just that the ACM doesn't understand magic.

    #

    Sample Output-1

    #

    Association for Computing Machinery (ACM) ACM ACM

    #

    The Association for Computing Machinery (ACM) cannot solve Cannot CANNOT solve CaN't solve

    all the problems in Computing Science (CS). Though large and having

    many resources at its disposal, the ACM does not use magic. Magic is not

    part of science, and hence not part of CS. Thank you for your

    suggestions.

    Signed, ACM

    #

    does notis notcannotAssociation for Computing Machinery (ACM)Computing Science (CS)

    #

    The Association for Computing Machinery (ACM) does not like magic.

    #

    It's not that the Association for Computing Machinery (ACM) won't use it, it's

    #

    just that the Association for Computing Machinery (ACM) does not understand magic.

    #

    Sample Input-2

    4 0

    "doesn't" -> "does not"

    "Doesn't" -> "&&&&&&&&"

    "DOESN'T" -> "%%%%%%%%"

    "doEsn't" -> "########"

    doesn't -> does not

    Doesn't -> &&&&&&&&

    DOESN'T -> %%%%%%%%

    doEsn't -> ########

    #

    Sample Output-2

    does not -> does not

    Does not -> &&&&&&&&

    DOES NOT -> %%%%%%%%

    ######## -> ########

    #

    [ EXP技术分享博客 ] 版权所有,转载请注明出处: http://exp-blog.com
  • 相关阅读:
    路由系统
    flask_sqlalchemy的使用
    input()输入语句
    注释
    Python 2017.1.5
    关于object网页播放器参数的设置,推荐博客系列
    LRU缓存,大神写的,值得借鉴
    object,网页播放器的相关属性设置
    js的apply和call方法
    count()函数在count()中参数的讨论
  • 原文地址:https://www.cnblogs.com/lyy289065406/p/2166128.html
Copyright © 2011-2022 走看看