Pointer Analysis
题目描述:
指针分析旨在确定在执行过程中可以通过程序中的特定指针变量访问哪些对象,这是静态程序分析的基本部分之一。现在,我们希望您对测试数据执行上下文无关的指针分析。
一个程序包含26个用小写字母表示的对象,每个对象也有26个用小写字母表示的成员变量(又称字段,它们可能指向某些对象的指针)。同时,在用大写字母指定的程序中有26个全局指针。
程序中有四种语句。我们使用[Variable]表示指针的名称,[Field]表示成员变量的名称,[Object]表示对象。
格式 | 例子 | 描述 | |
---|---|---|---|
分配 | [Variable] = [Object] | A = x | 指针A指向对象x(即x可通过A访问) |
分派 | [Variable] = [Variable] | A = B | 指针A可以指向可通过B访问的每个对象 |
储存 | [Variable].[Field] = [Variable] | A.f = B | 对于通过A可访问的每个对象o,o的成员变量f可以指向通过B可访问的每个对象 |
装入 | [Variable] = [Variable].[Field] | A = B.f | 对于通过B可访问的每个对象o,A可以指向通过o的成员变量f可访问的每个对象 |
操作顺序与输入顺序无关。 例如,在以下两个程序中,A和B都可以指向对象x和对象o。 这是因为,在现实世界中,很难准确预测语句的执行顺序和执行时间。
第一程序 | 第二程序 |
---|---|
A = o | B = A |
A = x | A = x |
B = A | A = o |
现在,要求您在由N个语句组成的给定程序上执行上下文无关的指针分析,并为每个指针输出它可以指向的对象。
输入描述:
输入的第一行包含一个整数
,代表程序中的语句数。 等号前后只有一个空格。
接下来的N行中的每一行都包含一个语句。
输出描述:
输出应包含26行。
在第i行中,输出第i个指针的名称(第i个大写字母),后跟冒号“:”和一个空格,然后按字母顺序列出可通过该指针访问的对象。
样例:
样例输入1:
5
B.f = A
C = B.f
C = x
A = o
B = o
样例输出1:
A: o
B: o
C: ox
D:
E:
F:
G:
H:
I:
J:
K:
L:
M:
N:
O:
P:
Q:
R:
S:
T:
U:
V:
W:
X:
Y:
Z:
样例输入2:
4
A = o
B.f = A
C = B.f
C = g
样例输出2:
A: o
B:
C: g
D:
E:
F:
G:
H:
I:
J:
K:
L:
M:
N:
O:
P:
Q:
R:
S:
T:
U:
V:
W:
X:
Y:
Z:
样例输入3:
3
A = o
B = A
A = x
样例输出3:
A: ox
B: ox
C:
D:
E:
F:
G:
H:
I:
J:
K:
L:
M:
N:
O:
P:
Q:
R:
S:
T:
U:
V:
W:
X:
Y:
Z:
样例好长…
思路:
这道题第一个重点就是理解题意:给定一些指针和对象,指针有的是全局指针,用大写字母表示,有的是成员指针,用大写字母+‘.’+小写表示。有的是对象,用小写字母表示。
现在你可以对给出的n个操作进行任意顺序的进行和重复使用,求对于每个指针,有多少种指向的可能。
第二个重点就是指针。
指针详解。
标准的大模拟题,本质上就是模拟指针,直接暴力求解即可。
伪代码(官方):
令pt(x)为指针x可能指向的对象集合:
具体做法详见代码(vector版,set版详见这篇博客)
:
代码好长好长好长好长…
#include<bits/stdc++.h>
using namespace std;
const int MAXN=52;
struct node{
int x,y;
node(){}
node(int _x,int _y){x=_x,y=_y;}
};
struct edge{
int a,b,c;
edge(){}
edge(int _a,int _b,int _c){a=_a,b=_b,c=_c;}
};
vector<node> vec1,tor1;
vector<edge> vec2,tor2;
queue<int> worklist;
string s1,s2,s3;
int pt[MAXN][MAXN],pt2[MAXN][MAXN][MAXN],n,len1,len3;
int main(){
scanf("%d",&n);
while(n--){
cin>>s1>>s2>>s3;
len1=s1.length();
len3=s3.length();
if(len1==1&&len3==1&&islower(s3[0]))
vec1.push_back(node((int)s1[0]-'A',(int)s3[0]-'a'));
if(len1==1&&len3==1&&isupper(s3[0]))
tor1.push_back(node((int)s1[0]-'A',(int)s3[0]-'A'));
if(len1==3&&len3==1)
vec2.push_back(edge((int)s1[0]-'A',(int)s1[2]-'a',(int)s3[0]-'A'));
if(len1==1&&len3==3)
tor2.push_back(edge((int)s1[0]-'A',(int)s3[2]-'a',(int)s3[0]-'A'));
}
for(int i=0;i<vec1.size();++i){
node p=vec1[i];
if(pt[p.x][p.y]) continue;
pt[p.x][p.y]=1;
worklist.push(p.x);
}
while(!worklist.empty()){
while(!worklist.empty()){
int x=worklist.front();
worklist.pop();
for(int i=0;i<tor1.size();++i){
node p=tor1[i];
if(p.y!=x) continue;
bool flag=false;
for(int j=0;j<26;++j){
if(!pt[p.x][j]&&pt[p.y][j]) flag=true;
pt[p.x][j]|=pt[p.y][j];
}
if(flag) worklist.push(p.x);
}
}
for(int i=0;i<vec2.size();++i){
edge p=vec2[i];
for(int j=0;j<26;++j){
if(!pt[p.a][j]) continue;
for(int k=0;k<26;++k){
pt2[j][p.b][k]|=pt[p.c][k];
}
}
}
for(int i=0;i<tor2.size();++i){
edge p=tor2[i];
bool flag=false;
for(int j=0;j<26;++j){
if(!pt[p.c][j]) continue;
for(int k=0;k<26;++k){
if(pt2[j][p.b][k]&&!pt[p.a][k]) flag=true;
pt[p.a][k]|=pt2[j][p.b][k];
}
}
if(flag) worklist.push(p.a);
}
}
for(int i=0;i<26;++i){
printf("%c: ",'A'+i);
for(int j=0;j<26;++j)
if(pt[i][j]) printf("%c",'a'+j);
puts("");
}
}