书上的算法很麻烦 转化成语法树又要费工夫
干脆用dfs搞了 用括号来分割区间 缺陷就是必须每个字母都有括号 然而加个括号大概是不碍事的(
(问就是处理的时候再都给加上)
简单证明:
因为所有的元素都是带括号的 因此可以看作是list型 那么只需要再讨论把里面的lexp-seq变成atom就行了
hhh 好好的实验怎么做成了一道implementation呢
//cyc
#include<bits/stdc++.h>
using namespace std;
/*
空を眺めると
そこには僕が居て
*/
using namespace std;
typedef pair<int,int> pii;
string str;
const int maxn=1e3;
map<int,string> mpk;
vector<pii> vec;
int len;
int step;
string s1="lexp-seq";
string s2="lexp";
string s3="list";
string s4="atom";
int lsts1;
int vis[maxn];
int cnt[maxn];//degree count
void dfs(int l,int r,int fa)
{
int cur=0;
stack<int> stk;
// int curp=l;
// int cnt=0;//parts
int curl=-1;
int lbcnt=0;
for(int i=l; i<=r; i++)
{
if(curl==-1)
{
if(str[i]=='(')
{
curl=i;
lbcnt++;
}
else if(str[i]!=')') //atom
{
//cnt++;
vec.push_back({fa,step});
mpk[step]=s2;
step++;
vec.push_back({step-1,step});
mpk[step]=s4;
step++;
}
}
else
{
if(str[i]==')')
{
lbcnt--;
if(!lbcnt)
{
//cnt++;
vec.push_back({fa,step});
mpk[step]=s2;
step++;
mpk[step]=s3;
vec.push_back({step-1,step});
step++;
mpk[step]="(";
vec.push_back({step-1,step});
step++;
mpk[step]=s1;
vec.push_back({step-2,step});
step++;
mpk[step]=")";
vec.push_back({step-3,step});
step++;
dfs(curl+1,i-1,step-2);
mpk[step]=s1;
lsts1=step;
vec.push_back({fa,step});
fa=step;
step++;
curl=-1;
}
}
if(str[i]=='(')lbcnt++;
}
}
}
int main()
{
cin>>str;
lsts1=-1;
len=str.size();
mpk[0]=s1;
step=1;
dfs(0,len-1,0);
for(pii it:vec){
cnt[it.first]++;
}
for(int i=0;i<vec.size();i++){
if(cnt[vec[i].second]==0&&mpk[vec[i].second]==s1)vis[i]=1;
}
ofstream out("text.dot");
out<<"digraph G{"<<endl;
for(int i=0;i<vec.size();i++){
if(!vis[i]){
out<<"a"<<vec[i].first<<"->"<<"a"<<vec[i].second<<";"<<endl;
}
}
for(int i=0;i<step;i++){
if(!cnt[i]&&mpk[i]==s1)continue;
else out<<"a"<<i<<" [label=\""<<mpk[i]<<"\""<<"];"<<endl;
}
out<<"}"<<endl;
return 0;
}
删除不必要的结点之后 把图和点的名称输出
实验要求画出语法树 所以就加入了graphviz(所以要装好graphviz哦
gcc编译之后获得了text.dot文件
然后命令行执行:
dot -Tpng text.dot -o text.png
就可以获得语法树了
以(A)(B)为例: