1.
Write a program to
simulate an FA that accepts
a. Union of the languages L1
and L2
#include<bits/stdc++.h>
using namespace std;
//code by PIYUSH
struct PairHash {
template <class T1, class T2>
size_t operator()(const pair<T1, T2>& pair) const {
return hash<T1>()(pair.first) ^ hash<T2>()(pair.second);
}
};
class DFA {
private:
int startState;
unordered_set<int> acceptedStates;
unordered_map<int, unordered_map<char, int>>
transitions;
public:
DFA(int startState) : startState(startState) {}
void addAcceptState(int state) {
acceptedStates.insert(state);
}
void addTransition(int fromState, char symbol, int toState) {
transitions[fromState][symbol] = toState;
}
int getStartState() const {
return startState;
}
bool isAcceptedState(int state) const {
return acceptedStates.count(state) > 0;
}
int getTransition(int state, char symbol) const {
if (transitions.count(state) &&
transitions.at(state).count(symbol)) {
return transitions.at(state).at(symbol);
}
return -1;
}
};
DFA unionDFA(const DFA& dfa1, const DFA& dfa2) {
DFA result(0);
queue<pair<int, int>> toProcess;
unordered_set<pair<int, int>,PairHash> visited;
unordered_map<pair<int, int>, int,PairHash> stateMapping;
int nextState = 1;
toProcess.push({dfa1.getStartState(), dfa2.getStartState()});
visited.insert({dfa1.getStartState(), dfa2.getStartState()});
stateMapping[{dfa1.getStartState(), dfa2.getStartState()}] = 0;
while (!toProcess.empty()) {
auto [state1, state2] = toProcess.front();
toProcess.pop();
int combinedState = stateMapping[{state1, state2}];
if (dfa1.isAcceptedState(state1) ||
dfa2.isAcceptedState(state2)) {
result.addAcceptState(combinedState);
}
for (char symbol = 'a'; symbol <= 'z'; ++symbol) {
int nextState1 = dfa1.getTransition(state1, symbol);
int nextState2 = dfa2.getTransition(state2, symbol);
pair<int, int> nextCombinedState = {nextState1,
nextState2};
if (nextState1 != -1 || nextState2 != -1) {
if (stateMapping.find(nextCombinedState) ==
stateMapping.end()) {
stateMapping[nextCombinedState] = nextState++;
}
result.addTransition(combinedState, symbol,
stateMapping[nextCombinedState]);
if (visited.find(nextCombinedState) == visited.end()) {
visited.insert(nextCombinedState);
toProcess.push(nextCombinedState);
}
}
}
}
return result;
}
bool simulateDFA(const DFA& dfa, const string& input) {
int currentState = dfa.getStartState();
for (char symbol : input) {
currentState = dfa.getTransition(currentState, symbol);
if (currentState == -1) {
return false;
}
}
return dfa.isAcceptedState(currentState);
}
int main()
{
DFA dfa1(0);
dfa1.addAcceptState(2);
dfa1.addTransition(0,'a',1);
dfa1.addTransition(1,'b',2);
DFA dfa2(0);
dfa2.addAcceptState(2);
dfa2.addTransition(0,'a',1);
dfa2.addTransition(1,'a',2);
DFA unionResult = unionDFA(dfa1,dfa2);
string input;
cout<<"Enter input string : ";
cin>>input;
if(simulateDFA(unionResult,input)){
cout<<"STRING IS ACCEPTED";
}else{
cout<<"STRING IS REJECTED";
}
return 0;
}
b. Intersection of the
languages L1 and L2
#include<bits/stdc++.h>
using namespace std;
// Code by PIYUSH
struct pair_hash {
template <class T1, class T2>
std::size_t operator()(const std::pair<T1, T2>& p) const {
return std::hash<T1>()(p.first) ^ (std::hash<T2>()(p.second)
<< 1);
}
};
class DFA {
private:
int startState;
unordered_set<int> acceptStates;
unordered_map<int, unordered_map<char, int>> transitions;
public:
DFA(int startState) : startState(startState) {}
void addAcceptState(int state) {
acceptStates.insert(state);
}
void addTransition(int fromState, char symbol, int toState) {
transitions[fromState][symbol] = toState;
}
int getStartState() const {
return startState;
}
bool isAcceptState(int state) const {
return acceptStates.count(state) > 0;
}
int getTransition(int state, char symbol) const {
if (transitions.count(state) &&
transitions.at(state).count(symbol)) {
return transitions.at(state).at(symbol);
}
return -1;
}
};
DFA intersectDFA(const DFA& dfa1, const DFA& dfa2) {
using StatePair = pair<int, int>;
DFA result(0);
queue<StatePair> toProcess;
unordered_map<StatePair, int, pair_hash> stateMapping;
int stateCounter = 0;
toProcess.push({dfa1.getStartState(), dfa2.getStartState()});
stateMapping[{dfa1.getStartState(), dfa2.getStartState()}] =
stateCounter++;
while (!toProcess.empty()) {
auto [state1, state2] = toProcess.front();
toProcess.pop();
int combinedState = stateMapping[{state1, state2}];
if (dfa1.isAcceptState(state1) && dfa2.isAcceptState(state2))
{
result.addAcceptState(combinedState);
}
for (char symbol = 'a'; symbol <= 'z'; ++symbol) {
int nextState1 = dfa1.getTransition(state1, symbol);
int nextState2 = dfa2.getTransition(state2, symbol);
if (nextState1 != -1 && nextState2 != -1) {
StatePair nextCombinedState = {nextState1,
nextState2};
if (stateMapping.find(nextCombinedState) ==
stateMapping.end()) {
stateMapping[nextCombinedState] = stateCounter++;
toProcess.push(nextCombinedState);
}
result.addTransition(combinedState, symbol,
stateMapping[nextCombinedState]);
}
}
}
return result;
}
bool simulateDFA(const DFA& dfa, const string& input) {
int currentState = dfa.getStartState();
for (char symbol : input) {
currentState = dfa.getTransition(currentState, symbol);
if (currentState == -1) {
return false;
}
}
return dfa.isAcceptState(currentState);
}
int main() {
DFA dfa1(0);
dfa1.addAcceptState(2);
dfa1.addTransition(0, 'a', 1);
dfa1.addTransition(1, 'b', 2);
DFA dfa2(0);
dfa2.addAcceptState(2);
dfa2.addTransition(0, 'a', 1);
dfa2.addTransition(1, 'a', 2);
DFA intersectionDFAResult = intersectDFA(dfa1, dfa2);
string input;
cout << "Enter input string: ";
cin >> input;
if (simulateDFA(intersectionDFAResult, input))
cout << "STRING IS ACCEPTED" << endl;
else
cout << "STRING IS REJECTED" << endl;
return 0;
}